python তালিকা তালিকা থেকে একটি সমতল তালিকা কিভাবে?




list multidimensional-array (20)

Python এ তালিকাগুলির তালিকা থেকে একটি সহজ তালিকা তৈরি করার জন্য একটি শর্টকাট আছে কিনা আমি অবাক।

আমি একটি লুপ জন্য যে করতে পারেন, কিন্তু সম্ভবত কিছু শীতল "এক-মাছ ধরার নৌকা" আছে? আমি এটি কমাতে চেষ্টা করেছি, কিন্তু আমি একটি ত্রুটি পেতে।

কোড

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
reduce(lambda x, y: x.extend(y), l)

ভুল বার্তা

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'

https://code.i-harness.com


অনিলের ফাংশনটির একটি খারাপ বৈশিষ্ট্য হল ব্যবহারকারীকে সর্বদা একটি খালি তালিকা হতে দ্বিতীয় যুক্তিটি নির্দিষ্ট করতে হবে [] । এটি পরিবর্তে একটি ডিফল্ট হতে হবে। পাইথন বস্তুগুলি যেভাবে কাজ করে, তার কারণে এইগুলি ফাংশনের ভিতরে সেট করা উচিত, আর্গুমেন্টে নয়।

এখানে একটি কাজ ফাংশন:

def list_flatten(l, a=None):
    #check a
    if a is None:
        #initialize with empty list
        a = []

    for i in l:
        if isinstance(i, list):
            list_flatten(i, a)
        else:
            a.append(i)
    return a

পরীক্ষামূলক:

In [2]: lst = [1, 2, [3], [[4]],[5,[6]]]

In [3]: lst
Out[3]: [1, 2, [3], [[4]], [5, [6]]]

In [11]: list_flatten(lst)
Out[11]: [1, 2, 3, 4, 5, 6]

অপারেটিং.ড্ড দিয়ে একটি বিভ্রান্তি বলে মনে হচ্ছে! যখন আপনি একসাথে দুটি তালিকা যুক্ত করেন, তখন তার জন্য সঠিক শব্দটি যোগ করা হয় না। operator.concat আপনি ব্যবহার করতে হবে কি।

যদি আপনি কার্যকরী চিন্তা করছেন, এটি এই হিসাবে সহজ:

>>> list2d = ((1, 2, 3), (4, 5, 6), (7,), (8, 9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)

আপনি ক্রম টাইপ সম্মান কমাতে দেখুন, তাই যখন আপনি একটি tuple সরবরাহ, আপনি একটি tuple ফিরে পেতে। এর একটি তালিকা দিয়ে চেষ্টা করা যাক ::

>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

আহ, আপনি একটি তালিকা ফিরে পেতে।

কর্মক্ষমতা সম্পর্কে কিভাবে ::

>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> %timeit list(itertools.chain.from_iterable(list2d))
1000000 loops, best of 3: 1.36 µs per loop

from_iterable বেশ দ্রুত! কিন্তু এটি concat সঙ্গে কমাতে কোন তুলনা।

>>> list2d = ((1, 2, 3),(4, 5, 6), (7,), (8, 9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop

আপনি itertools.chain() ব্যবহার করতে পারেন:

>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))

অথবা, পাইথন> = 2.6 এ, itertools.chain.from_iterable() ব্যবহার করুন যা তালিকার আনপ্যাকিংয়ের প্রয়োজন নেই:

>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))

এই পদ্ধতিটি বিতর্কিতভাবে তুলনায় আরও বেশি [item for sublist in l for item in sublist] এবং আরও দ্রুত বলে মনে হচ্ছে:

[[email protected]]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
10000 loops, best of 3: 24.2 usec per loop
[[email protected]]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 45.2 usec per loop
[[email protected]]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 488 usec per loop
[[email protected]]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 522 usec per loop
[[email protected]]$ python --version
Python 2.7.3

আপনি numpy ব্যবহার করতে পারেন:
flat_list = list(np.concatenate(list_of_list))


আপনি যদি ক্লিনার চেহারাটির জন্য একটি ক্ষুদ্র গতির গতি ছেড়ে দিতে ইচ্ছুক হন তবে আপনি numpy.concatenate().tolist() অথবা numpy.concatenate().ravel().tolist() ব্যবহার করতে পারেন numpy.concatenate().ravel().tolist()

import numpy

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] * 99

%timeit numpy.concatenate(l).ravel().tolist()
1000 loops, best of 3: 313 µs per loop

%timeit numpy.concatenate(l).tolist()
1000 loops, best of 3: 312 µs per loop

%timeit [item for sublist in l for item in sublist]
1000 loops, best of 3: 31.5 µs per loop

আপনি ডক্স numpy.concatenate এবং numpy.ravel ডক্স এখানে আরও জানতে পারেন


আমি perfplot (খনি একটি পোষা প্রকল্প, মূলত timeit কাছাকাছি একটি wrapper) সঙ্গে সবচেয়ে প্রস্তাবিত সমাধান পরীক্ষা, এবং পাওয়া যায়

list(itertools.chain.from_iterable(a))

দ্রুততম সমাধান হতে (যদি 10 টির বেশি তালিকা সংহত হয়)।

প্লট পুনরুত্পাদন কোড:

import functools
import itertools
import numpy
import operator
import perfplot


def forfor(a):
    return [item for sublist in a for item in sublist]


def sum_brackets(a):
    return sum(a, [])


def functools_reduce(a):
    return functools.reduce(operator.concat, a)


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(numpy.array(a).flat)


def numpy_concatenate(a):
    return list(numpy.concatenate(a))


perfplot.show(
    setup=lambda n: [list(range(10))] * n,
    kernels=[
        forfor, sum_brackets, functools_reduce, itertools_chain, numpy_flat,
        numpy_concatenate
        ],
    n_range=[2**k for k in range(16)],
    logx=True,
    logy=True,
    xlabel='num lists'
    )

কেউ নুম্পির flat ব্যবহার করতে পারে:

import numpy as np
list(np.array(l).flat)

সম্পাদন 11/02/2016: শুধুমাত্র sublists অভিন্ন মাত্রা আছে যখন কাজ করে।


নিম্নলিখিত আমার কাছে সহজ মনে হয়:

>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print (np.concatenate(l))
[1 2 3 4 5 6 7 8 9]

যদি আপনি কোনও তথ্য-কাঠামোকে ফ্ল্যাট করতে চান যেখানে আপনি এটি গভীরভাবে নিস্তেজ না হন তবে এটি iteration_utilities.deepflatten 1 ব্যবহার করতে পারে।

>>> from iteration_utilities import deepflatten

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

এটি একটি জেনারেটর তাই আপনাকে ফলাফলটিকে একটি list নিক্ষেপ করতে বা স্পষ্টভাবে এটির পুনরাবৃত্তি করতে হবে।

কেবলমাত্র এক স্তরকে ফ্ল্যাট করতে এবং যদি প্রতিটি আইটেম নিজেই কার্যকর হয় তবে আপনি iteration_utilities.flatten ব্যবহার করতে পারেন যা নিজেই itertools.chain.from_iterable কাছাকাছি একটি পাতলা মোড়ক itertools.chain.from_iterable :

>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

শুধু কিছু সময় যোগ করার জন্য (নিক Schlömer উত্তরটির উপর ভিত্তি করে যা এই উত্তরটিতে উপস্থাপিত ফাংশনটি অন্তর্ভুক্ত করে নি):

এটি একটি লগ-লগ প্লট যা ব্যয়বহুল মানগুলির বিস্তৃত পরিসরের জন্য উপযুক্ত। গুণগত যুক্তি জন্য: নিম্নতর ভাল।

ফলাফলগুলি দেখায় যে যদি কেবলমাত্র কয়েকটি অভ্যন্তরীণ ইথারবেল থাকে তবে sum দ্রুততম হবে, তবে itertools.chain.from_iterable জন্য শুধুমাত্র itertools.chain.from_iterable , iteration_utilities.deepflatten বা nested বোঝার সাথে itertools.chain.from_iterable দ্রুততম কার্যকারিতা রয়েছে (ইতিমধ্যে নিক Schlömer দ্বারা লক্ষ্য করেছেন)।

from itertools import chain
from functools import reduce
from collections import Iterable  # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten

def nested_list_comprehension(lsts):
    return [item for sublist in lsts for item in sublist]

def itertools_chain_from_iterable(lsts):
    return list(chain.from_iterable(lsts))

def pythons_sum(lsts):
    return sum(lsts, [])

def reduce_add(lsts):
    return reduce(lambda x, y: x + y, lsts)

def pylangs_flatten(lsts):
    return list(flatten(lsts))

def flatten(items):
    """Yield items from any nested iterable; see REF."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            yield from flatten(x)
        else:
            yield x

def reduce_concat(lsts):
    return reduce(operator.concat, lsts)

def iteration_utilities_deepflatten(lsts):
    return list(deepflatten(lsts, depth=1))


from simple_benchmark import benchmark

b = benchmark(
    [nested_list_comprehension, itertools_chain_from_iterable, pythons_sum, reduce_add,
     pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
    arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
    argument_name='number of inner lists'
)

b.plot()

1 দাবিঃ আমি সেই লাইব্রেরীর লেখক


হিটের জন্য কাজ করে এমন আরেকটি অস্বাভাবিক পদ্ধতি- এবং পূর্ণসংখ্যার একক তালিকা:

from typing import List


def flatten(l: list) -> List[int]:
    """Flatten an arbitrary deep nested list of lists of integers.

    Examples:
        >>> flatten([1, 2, [1, [10]]])
        [1, 2, 1, 10]

    Args:
        l: Union[l, Union[int, List[int]]

    Returns:
        Flatted list of integer
    """
    return [int(i.strip('[ ]')) for i in str(l).split(',')]

underscore.py প্যাকেজ ফ্যানের জন্য সহজ কোড

from underscore import _
_.flatten([[1, 2, 3], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

এটি সমস্ত flatten সমস্যার সমাধান (কোন তালিকা আইটেম বা জটিল নেস্টিং)

from underscore import _
# 1 is none list item
# [2, [3]] is complex nesting
_.flatten([1, [2, [3]], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

আপনি underscore.py দিয়ে ইনস্টল করতে পারেন

pip install underscore.py

matplotlib.cbook.flatten() নেস্টেড তালিকাগুলির জন্য কাজ করবে এমনকি যদি তারা উদাহরণের চেয়ে গভীরভাবে ঘুরে বেড়ায়।

import matplotlib
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
print(list(matplotlib.cbook.flatten(l)))
l2 = [[1, 2, 3], [4, 5, 6], [7], [8, [9, 10, [11, 12, [13]]]]]
print list(matplotlib.cbook.flatten(l2))

ফলাফল:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

এটি আন্ডারস্কোর চেয়ে 18x দ্রুত ._। ফ্ল্যাট:

Average time over 1000 trials of matplotlib.cbook.flatten: 2.55e-05 sec
Average time over 1000 trials of underscore._.flatten: 4.63e-04 sec
(time for underscore._)/(time for matplotlib.cbook) = 18.1233394636

দ্রষ্টব্য : এটি ব্যবহার করে কারণ পাইথন 3.3+ এ প্রযোজ্য yield_fromsixএটি একটি তৃতীয় পক্ষের প্যাকেজ, যদিও এটি স্থিতিশীল। অন্যথায়, আপনি ব্যবহার করতে পারেন sys.version

ক্ষেত্রে obj = [[1, 2,], [3, 4], [5, 6]], এখানে সমস্ত সমাধান তালিকা বোঝার সহ, ভাল itertools.chain.from_iterable

তবে, এই সামান্য আরো জটিল ক্ষেত্রে বিবেচনা করুন:

>>> obj = [[1, 2, 3], [4, 5], 6, 'abc', [7], [8, [9, 10]]]

এখানে বিভিন্ন সমস্যা আছে:

  • এক উপাদান,, 6শুধু একটি scalar হয়; এটি পুনরাবৃত্তিযোগ্য নয়, তাই উপরের রুট এখানে ব্যর্থ হবে।
  • এক উপাদান 'abc', হয় টেকনিক্যালি iterable (সমস্ত strগুলি আছে)। যাইহোক, লাইনগুলির মধ্যে একটু পড়া, আপনি এটির মতো আচরণ করতে চান না - আপনি এটি একটি একক উপাদান হিসাবে আচরণ করতে চান।
  • চূড়ান্ত উপাদান, [8, [9, 10]]নিজেই একটি nested পুনরাবৃত্তিযোগ্য। বেসিক তালিকা বোঝার এবং chain.from_iterableশুধুমাত্র "1 স্তর নিচে।"

আপনি নিম্নরূপ এই প্রতিকার করতে পারেন:

>>> from collections import Iterable
>>> from six import string_types

>>> def flatten(obj):
...     for i in obj:
...         if isinstance(i, Iterable) and not isinstance(i, string_types):
...             yield from flatten(i)
...         else:
...             yield i


>>> list(flatten(obj))
[1, 2, 3, 4, 5, 6, 'abc', 7, 8, 9, 10]

এখানে, আপনি চেক করুন যে উপ-উপাদান (1) সঙ্গে iterable হয় Iterable, থেকে একটি এবিসি itertools, কিন্তু তা নিশ্চিত করার জন্য (2) উপাদান চান না "STRING মত।"


লেখক থেকে নোট : এই অদক্ষ। কিন্তু মজা, monads ভয়ঙ্কর কারণ। এটা পাইথন কোড উত্পাদন জন্য উপযুক্ত নয়।

>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

এটি কেবলমাত্র প্রথম যুক্তিটিতে প্রেরণযোগ্য উপাদানগুলিকে গণনা করে, দ্বিতীয় আর্গুমেন্টকে সমষ্টিগত প্রাথমিক মান হিসেবে বিবেচনা করে (যদি না দেওয়া হয়, 0 পরিবর্তে ব্যবহৃত হয় এবং এই ক্ষেত্রে আপনাকে একটি ত্রুটি দেবে)।

কারণ আপনি নেস্টেড তালিকাগুলি সংকলন করছেন, আপনি প্রকৃতপক্ষে [1,3]+[2,4] sum([[1,3],[2,4]],[]) ফলে পাবেন যা [1,3,2,4]

তালিকা তালিকা শুধুমাত্র কাজ করে নোট। তালিকা তালিকা তালিকা জন্য, আপনি অন্য সমাধান প্রয়োজন হবে।


আমি দ্রুততম সমাধান খুঁজে পেয়েছি (যাইহোক বড় তালিকা জন্য):

import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()

সম্পন্ন! আপনি অবশ্যই তালিকাটি নির্বাহ করে এটি একটি তালিকাতে ফিরিয়ে আনতে পারেন (l)


আমি সম্প্রতি একটি পরিস্থিতি জুড়ে এসেছি যেখানে আমি যেমন sublists মধ্যে স্ট্রিং এবং সংখ্যাসূচক তথ্য মিশ্রিত ছিল

test = ['591212948',
['special', 'assoc', 'of', 'Chicago', 'Jon', 'Doe'],
['Jon'],
['Doe'],
['fl'],
92001,
555555555,
'hello',
['hello2', 'a'],
'b',
['hello33', ['z', 'w'], 'b']]

যেখানে পদ্ধতি flat_list = [item for sublist in test for item in sublist]কাজ করে না। তাই, আমি 1+ স্তরের sublists জন্য নিচের সমাধান নিয়ে এসেছি

def concatList(data):
    results = []
    for rec in data:
        if type(rec) == list:
            results += rec
            results = concatList(results)
        else:
            results.append(rec)
    return results

এবং ফলাফল

In [38]: concatList(test)
Out[38]:
 Out[60]:
['591212948',
'special',
'assoc',
'of',
'Chicago',
'Jon',
'Doe',
'Jon',
'Doe',
'fl',
92001,
555555555,
'hello',
'hello2',
'a',
'b',
'hello33',
'z',
'w',
'b']

তালিকা reduceথেকে functoolsএবং addঅপারেটর ব্যবহার করে একটি সহজ recursive পদ্ধতি :

>>> from functools import reduce
>>> from operator import add
>>> flatten = lambda lst: [lst] if type(lst) is int else reduce(add, [flatten(ele) for ele in lst])
>>> flatten(l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

ফাংশন হিসাবে পরামিতি flattenলাগে lst। এটা সব উপাদান loops lstপর্যন্ত পৌঁছনো পূর্ণসংখ্যার (এছাড়াও পরিবর্তন করতে পারেন intথেকে float, strযা দূরতম পুনরাবৃত্তির ফেরত মান যোগ করা হয় অন্য ডেটা ধরনের জন্য, ইত্যাদি)।

forলুপ এবং মণ্যাডের মতো পদ্ধতির বিপরীতে , এটি একটি সাধারণ সমাধান তালিকা গভীরতার দ্বারা সীমাবদ্ধ নয় । উদাহরণস্বরূপ, 5 এর গভীরতা সহ একটি তালিকা একইভাবে ফ্ল্যাট করা যেতে পারে l:

>>> l2 = [[3, [1, 2], [[[6], 5], 4, 0], 7, [[8]], [9, 10]]]
>>> flatten(l2)
[3, 1, 2, 6, 5, 4, 0, 7, 8, 9, 10]

def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])

flat_list = []
for i in list_of_list:
    flat_list+=i

এই কোডটি ঠিক ভাবেই তালিকাটি প্রসারিত করে জরিমানা করে। যদিও এটি অনেক অনুরূপ কিন্তু শুধুমাত্র লুপের জন্য একটি। তাই loops জন্য 2 যোগ চেয়ে কম জটিলতা আছে।


flat_list = [item for sublist in l for item in sublist]

যার অর্থ:

for sublist in l:
    for item in sublist:
        flat_list.append(item)

এতদূর পোস্ট শর্টকাট চেয়ে দ্রুত। ( l ফ্ল্যাট করা তালিকা।)

এখানে একটি অনুরূপ ফাংশন:

flatten = lambda l: [item for sublist in l for item in sublist]

প্রমাণ হিসাবে, সর্বদা, আপনি মান লাইব্রেরিতে timeit মডিউল ব্যবহার করতে পারেন:

$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 1.1 msec per loop

ব্যাখ্যা: উপর ভিত্তি করে শর্টকাটগুলি (সমষ্টিতে নিখরচায় ব্যবহার সহ), প্রয়োজনের, O(L**2) যখন এল sublists হয় - যেমন মধ্যবর্তী ফলাফল তালিকা দীর্ঘতর থাকে, প্রতিটি ধাপে একটি নতুন মধ্যবর্তী ফলাফল তালিকা বস্তু বরাদ্দ করা হয়, এবং পূর্ববর্তী মধ্যবর্তী ফলাফলের সমস্ত আইটেম অনুলিপি করা উচিত (পাশাপাশি শেষে যুক্ত কয়েকটি নতুন)। সুতরাং (সরলতার জন্য এবং সাধারণভাবে প্রকৃত ক্ষতি না করে) বলুন আপনার প্রতিটি আইটেমগুলির এল Sublists আছে: প্রথম আইটেমটি আমি L-1 বার, দ্বিতীয় আইটেম L-2 বার এবং আরও অনুলিপি করা হয়; মোট কপিগুলির সংখ্যা আমি বার বার 1 থেকে এক্স এর জন্য এক্স এর সমষ্টি, অর্থাৎ, I * (L**2)/2

তালিকা বোঝার কেবল একটি তালিকা তৈরি করে, একবার, এবং প্রতিটি আইটেমকে অনুলিপি করে (বাসস্থানটির আসল স্থানে থেকে ফলাফল তালিকায়) ঠিক একই সময়ে।





flatten