তালিকার একটি অনিয়মিত তালিকা সমতল করুন


440

হ্যাঁ, আমি জানি এই বিষয়টি আগে ( এখানে , এখানে , এখানে , এখানে) আচ্ছাদিত ছিল ) , তবে যতদূর আমি জানি, একটি ব্যতীত সমস্ত সমাধান এই জাতীয় তালিকায় ব্যর্থ হয়েছে:

L = [[[1, 2, 3], [4, 5]], 6]

যেখানে কাঙ্ক্ষিত আউটপুট

[1, 2, 3, 4, 5, 6]

বা সম্ভবত আরও ভাল, একটি পুনরাবৃত্তি। একমাত্র সমাধান যা আমি দেখেছি যে নির্বিচারে বাসা বাঁধার জন্য কাজ করে তা এই প্রশ্নের মধ্যে পাওয়া যায় :

def flatten(x):
    result = []
    for el in x:
        if hasattr(el, "__iter__") and not isinstance(el, basestring):
            result.extend(flatten(el))
        else:
            result.append(el)
    return result

flatten(L)

এটি কি সেরা মডেল? আমি কি কিছু উপেক্ষা করেছি? কোন সমস্যা?


16
এই প্রশ্নের অনেকগুলি উত্তর এবং এত ক্রিয়া রয়েছে তা সত্যই বোঝায় যে এটি কোথাও একটি বিল্ট-ইন ফাংশন হওয়া উচিত, তাই না? এটি বিশেষত খুব খারাপ যে
সংকলনটি

3
আমি বলব যে পাইথনের যা সত্যই প্রয়োজন তা অন্য বিল্টিনের চেয়ে অখণ্ড পুনরাবৃত্তি।
কাদামাটি

2
@ মিটেনচোপস: সম্পূর্ণরূপে একমত নয় যে লোকেরা স্পষ্টতই খারাপ এপিআই / অতি জটিল ডেটা কাঠামো নিয়ে কাজ করে (কেবল একটি নোট: listসমজাতীয় হওয়ার উদ্দেশ্যে) এর অর্থ এই নয় যে এটি একটি পাইথনের দোষ এবং এই জাতীয় কাজের জন্য আমাদের একটি
বিল্টিন দরকার

1
আপনি যদি আপনার প্রকল্পে একটি প্যাকেজ যুক্ত করতে সক্ষম হন - আমি মনে করি যে আরও_আরটিওলস কোডস সলিউশনটি এটি সর্বোত্তমভাবে করবে। : এই উত্তর থেকে stackoverflow.com/a/40938883/3844376
viddik13

উত্তর:


382

জেনারেটর ফাংশনগুলি ব্যবহার করা আপনার উদাহরণটি পড়ার জন্য আরও সহজ করে তুলতে পারে এবং সম্ভবত কার্য সম্পাদনকে বাড়িয়ে তুলতে পারে।

পাইথন 2

def flatten(l):
    for el in l:
        if isinstance(el, collections.Iterable) and not isinstance(el, basestring):
            for sub in flatten(el):
                yield sub
        else:
            yield el

আমি ইটারেবল এবিসি ব্যবহার করেছি 2.6-এ যোগ করা ।

পাইথন ঘ

পাইথন 3-তে, এটি basestringআর নেই, তবে আপনি strএবং এর একটি tuple ব্যবহার করতে পারেনbytes একই এফেক্ট পেতে।

yield fromঅপারেটর একটি সময়ে জেনারেটরের এক থেকে একটি আইটেম ফেরৎ। সাবজিনেটরকে অর্পণ করার জন্য এই বাক্য গঠনটি 3.3-এ যুক্ত করা হয়েছিল

def flatten(l):
    for el in l:
        if isinstance(el, collections.Iterable) and not isinstance(el, (str, bytes)):
            yield from flatten(el)
        else:
            yield el

6
এই পৃষ্ঠার সমস্ত পরামর্শগুলির মধ্যে, আমি এই কাজটি করার সময় এই একমাত্র l = ([[chr(i),chr(i-32)] for i in xrange(ord('a'), ord('z')+1)] + range(0,9))স্ন্যাপে এই তালিকাটিকে সমতল করে তুলেছিল list(flatten(l))। অন্য সমস্ত, কাজ শুরু করবে এবং চিরকালের জন্য গ্রহণ করবে!
nemesisfixx

7
এটি অভিধানকেও সমতল করে তোলে। আপনি কি collections.Sequenceপরিবর্তে ব্যবহার করতে চান collections.Iteratable?
জোছ

1
এটি এমন জিনিসগুলির সাথে কাজ করে না যা প্রাথমিকভাবে তালিকাভুক্ত নয়, যেমন for i in flatten(42): print (i)। এটি লস্টের isinstanceবাইরে-ধরে এবং অন্য-ধারাটি সরিয়ে নিয়ে স্থির করা যেতে পারে for el। (তারপরে আপনি এটিতে যে কোনও কিছু ফেলতে পারেন, এবং এটি এটি থেকে একটি
সমতল

6
পাইথন ৩.7-এর জন্য ব্যবহার collections.Iterableকরা অবনতিযুক্ত। collections.abc.Iterableপরিবর্তে ব্যবহার করুন।
ডগ

5
আসলে, পুনরাবৃত্তি প্রয়োজন হয় না । এই নির্দিষ্ট ক্ষেত্রে পুনরাবৃত্তি ব্যবহার করা সর্বোত্তম সমাধান নয় কারণ এটি গভীরভাবে নেস্টেড তালিকাগুলিতে (গভীরতা> 1000) ক্রাশ হবে। তবে যদি আপনার কোনও সুরক্ষিত থাকার লক্ষ্য না থাকে তবে হ্যাঁ পুনরাবৃত্তির কাজটি আরও ভাল কারণ তারা পড়া / লেখার পক্ষে সহজ।
সিগ্লেসেট

50

আমার সমাধান:

import collections


def flatten(x):
    if isinstance(x, collections.Iterable):
        return [a for i in x for a in flatten(i)]
    else:
        return [x]

আরও কিছুটা সংক্ষিপ্ত, তবে প্রায় একই।


5
আপনি কেবল try: iter(x)এটি পুনরাবৃত্তিযোগ্য কিনা তা পরীক্ষা করার জন্য আপনি কোনও কিছু আমদানি না করেই এটি করতে পারেন … তবে আমি মনে করি না যে স্টাডলিব মডিউলটি আমদানি করা একটি এড়িয়ে যাওয়া মূল্যহীন।
অবতারিত

8
লক্ষণীয় যে এই আইটেমটি কেবলমাত্র যদি সমস্ত আইটেম টাইপ করা হয় তবেই কাজ করেint
আলফাসিন

1
এটি আরও সংক্ষিপ্ত করে তুলতে পারে def flatten(x): return [a for i in x for a in flatten(i)] if isinstance(x, collections.Iterable) else [x]- তবে পাঠযোগ্যতা এখানে বিষয়গত হতে পারে।
জিরো

4
এটি স্ট্রিংগুলিতে কাজ করে না কারণ স্ট্রিংগুলিও পুনরাবৃত্ত হয়। শর্তটি প্রতিস্থাপন করুনif isinstance(x, collections.Iterable) and not isinstance(x, basestring)
এন্ডিস

36

পুনরাবৃত্তি এবং হাঁসের টাইপিং ব্যবহার করে জেনারেটর (পাইথন 3 এর জন্য আপডেট করা):

def flatten(L):
    for item in L:
        try:
            yield from flatten(item)
        except TypeError:
            yield item

list(flatten([[[1, 2, 3], [4, 5]], 6]))
>>>[1, 2, 3, 4, 5, 6]

1
ধন্যবাদ, পাইথন 3 এর জন্য এটি দুর্দান্ত কাজ করে for i in flatten(item): yield i
2..x এর

তালিকা (সমতল ([['এক্স'], 'ওয়াই'])) ২ এক্স এক্স ভেরিয়েন্টে ব্যর্থ হয়েছে
স্টেন

@ ব্যবহারকারী 1019129 আপনার উপরে আমার মন্তব্য দেখুন
ডানসালমো

হ্যাঁ এটি চক্রের সাথে ব্যর্থ হয় .. আমি মনে করি কারণ একটি স্ট্রিংটিও একটি "অ্যারে"
চরিত্রগুলির

35

@ অ্যান্ডবু-র পুনঃবিবেচনামূলক সমাধানের জেনারেটর সংস্করণ, @ অ্যান্ড্রু একটি মন্তব্যে অনুরোধ করেছেন:

def genflat(l, ltypes=collections.Sequence):
    l = list(l)
    i = 0
    while i < len(l):
        while isinstance(l[i], ltypes):
            if not l[i]:
                l.pop(i)
                i -= 1
                break
            else:
                l[i:i + 1] = l[i]
        yield l[i]
        i += 1

এই জেনারেটরের সামান্য সরলীকৃত সংস্করণ:

def genflat(l, ltypes=collections.Sequence):
    l = list(l)
    while l:
        while l and isinstance(l[0], ltypes):
            l[0:1] = l[0]
        if l: yield l.pop(0)

এটি নেস্টেড তালিকাগুলি দ্বারা গঠিত গাছের প্রাক-অর্ডার ট্রভারসালাল। কেবল পাতাগুলিই ফিরে আসে। নোট করুন যে এই বাস্তবায়নটি আরও ভাল বা আরও খারাপের জন্য মূল ডেটা কাঠামো গ্রাস করবে। দুটিই মূল গাছ সংরক্ষণ করে এমন একটি লেখা মজাদার হতে পারে তবে তালিকার এন্ট্রিগুলিও অনুলিপি করতে হবে না।
অ্যান্ড্রু ওয়াগনার

6
আমি মনে করি আপনার স্ট্রিংগুলির জন্য পরীক্ষা করা দরকার - যেমন ক্রিশ্চিয়ানের সমাধান হিসাবে "যুক্ত করুন এবং না (আই [0], বেসস্ট্রিং)") অন্যথায় আপনি l এর আশেপাশে একটি অসীম লুপ পেয়েছেন [0: 1] = l [0]
সি-urchin

এটি একটি জেনারেটর তৈরির একটি ভাল উদাহরণ, তবে সি-urchin হিসাবে উল্লেখ করা হয়েছে, যখন ক্রমটিতে স্ট্রিং রয়েছে তখন অ্যালগরিদম নিজেই ব্যর্থ হয়।
ড্যানিয়েল 'ডাং' গ্রিফিথ

28

এখানে আমার পুনরাবৃত্ত সমতলতার ক্রিয়াকলাপের সংস্করণ যা টিপলস এবং তালিকাগুলি উভয়ই পরিচালনা করে এবং আপনাকে অবস্থানগত আর্গুমেন্টের কোনও মিশ্রণ দিতে দেয়। একটি জেনারেটর প্রদান করে যা পুরো ক্রমটি ক্রমে উত্পাদন করে, আরগ দিয়ে আর্গ:

flatten = lambda *n: (e for a in n
    for e in (flatten(*a) if isinstance(a, (tuple, list)) else (a,)))

ব্যবহার:

l1 = ['a', ['b', ('c', 'd')]]
l2 = [0, 1, (2, 3), [[4, 5, (6, 7, (8,), [9]), 10]], (11,)]
print list(flatten(l1, -2, -1, l2))
['a', 'b', 'c', 'd', -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

1
মহান সমাধান, যদিও সহায়ক যদি আপনি কি বর্ণনা করতে কিছু মন্তব্য জুড়েছে হবে e, a, nপড়ুন
ক্রিস্টফ পাল

2
@WolfgangKuehne: চেষ্টা argsজন্য n, intermediate(অথবা খাটো midঅথবা আপনি পছন্দ হতে পারে element) জন্য aএবং resultজন্য e, তাই:flatten = lambda *args: (result for mid in args for result in (flatten(*mid) if isinstance(mid, (tuple, list)) else (mid,)))
পরবর্তী ঘোষণা না হওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

এটি তুলনায় উল্লেখযোগ্যভাবে দ্রুত compiler.ast.flatten। দুর্দান্ত, কমপ্যাক্ট কোড, যে কোনও (আমার মনে হয়) অবজেক্ট টাইপের জন্য কাজ করে।
বিসিডিয়ান

বাহ এটি সর্বাধিক ভোট দেওয়া এবং স্বীকৃত উত্তর হওয়া উচিত ... কবজির মতো কাজ করে!
ইউ 10-ফরওয়ার্ড

27

flattenঅজগরটির পুনরাবৃত্তি সীমা এড়ানোর এই সংস্করণটি (এবং এটি নির্বিচারে গভীর, নেস্টেড পুনরাবৃত্তির সাথে কাজ করে)। এটি এমন একটি জেনারেটর যা স্ট্রিং এবং স্বেচ্ছাচারিত পুনরাবৃত্তিকে (এমনকি অসীম এমনকি) পরিচালনা করতে পারে।

import itertools as IT
import collections

def flatten(iterable, ltypes=collections.Iterable):
    remainder = iter(iterable)
    while True:
        first = next(remainder)
        if isinstance(first, ltypes) and not isinstance(first, (str, bytes)):
            remainder = IT.chain(first, remainder)
        else:
            yield first

এখানে এর উদাহরণ দেখানো কয়েকটি উদাহরণ রয়েছে:

print(list(IT.islice(flatten(IT.repeat(1)),10)))
# [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

print(list(IT.islice(flatten(IT.chain(IT.repeat(2,3),
                                       {10,20,30},
                                       'foo bar'.split(),
                                       IT.repeat(1),)),10)))
# [2, 2, 2, 10, 20, 30, 'foo', 'bar', 1, 1]

print(list(flatten([[1,2,[3,4]]])))
# [1, 2, 3, 4]

seq = ([[chr(i),chr(i-32)] for i in range(ord('a'), ord('z')+1)] + list(range(0,9)))
print(list(flatten(seq)))
# ['a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F', 'g', 'G', 'h', 'H',
# 'i', 'I', 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N', 'o', 'O', 'p', 'P',
# 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T', 'u', 'U', 'v', 'V', 'w', 'W', 'x', 'X',
# 'y', 'Y', 'z', 'Z', 0, 1, 2, 3, 4, 5, 6, 7, 8]

যদিও flattenঅসীম জেনারেটরগুলি পরিচালনা করতে পারে তবে এটি অসীম বাসা বাঁধতে পারে না:

def infinitely_nested():
    while True:
        yield IT.chain(infinitely_nested(), IT.repeat(1))

print(list(IT.islice(flatten(infinitely_nested()), 10)))
# hangs

1
এবিসি ইটারেবল বা এবিসি সিকোয়েন্স ব্যবহার করবেন কিনা তা নিয়ে কোনও sensক্যমত্য?
উইম

sets, dicts, deques, listiterators, generators, Filehandles, এবং কাস্টম শ্রেণীর __iter__সংজ্ঞায়িত সমস্ত উদাহরণ হয় collections.Iterable, কিন্তু না collections.Sequence। একটি সমতল করার ফলাফলটি dictকিছুটা ifif হয় তবে অন্যথায়, আমি মনে করি এর collections.Iterableচেয়ে ভাল একটি ডিফল্ট collections.Sequence। এটি অবশ্যই আরও উদার।
আনটবু

@ উইম: ব্যবহারে একটি সমস্যা collections.Iterableহ'ল এর মধ্যে রয়েছে অসীম জেনারেটর। আমি আমার উত্তর হ্যান্ডেল এই ক্ষেত্রে পরিবর্তন করেছি।
আনটবু

1
এটি তৃতীয় এবং চতুর্থ উদাহরণগুলির জন্য কাজ করে বলে মনে হচ্ছে না। এটা তোলে ছোঁড়ার StopIteration। এছাড়াও, দেখে মনে হচ্ছে while True: first = next(remainder) এটি প্রতিস্থাপন করা যেতে পারে for first in remainder:
জর্জি

@ জর্জি এটি এ ফ্ল্যাটনের শরীরে আবদ্ধ করার সাথে সংশোধন করা যেতে পারে try-except StopIteration block
Baduker

12

আরও একটি আকর্ষণীয় এখানে এখানে আরও একটি উত্তর ...

import re

def Flatten(TheList):
    a = str(TheList)
    b,crap = re.subn(r'[\[,\]]', ' ', a)
    c = b.split()
    d = [int(x) for x in c]

    return(d)

মূলত, এটি নেস্টেড তালিকাকে স্ট্রিংয়ে রূপান্তর করে, নেস্টেড সিনট্যাক্সটি সরিয়ে ফেলার জন্য একটি রেইজেক্স ব্যবহার করে এবং ফলাফলটিকে আবার (সমতল) তালিকায় রূপান্তর করে।


আপনি যদি মান মানগুলি ব্যতীত অন্য কোনওটিতে এটি সাধারণকরণের চেষ্টা করেন তবে এটি মজাদার হবে, উদাহরণস্বরূপ, [['C=64', 'APPLE ]['], ['Amiga', 'Mac', 'ST']]:) অন্যদিকে, একটি তালিকা রয়েছে যা এতে রয়েছে, এটি অন্য উত্তরের চেয়ে কিছুটা ভাল করবে, একটি উত্থাপন করে পরিবর্তে শুধু আপনার না হওয়া পর্যন্ত লুপিং ছাড়া মেমরি রান আউট / recursing যতক্ষণ না আপনি স্ট্যাক এক্সস্ট ...
abarnert

মূল প্রম্পটটি পূর্ণসংখ্যার একটি তালিকা সমতলকরণ সম্পর্কে ছিল। যদি আপনি কেবল তালিকা বোধগম্যটিকে ডি = [x এর জন্য x] করে পরিবর্তন করেন তবে এটি আপনার নমুনার জন্য ভাল কাজ করা উচিত।
কাদামাটি

প্রথমত, [x for x in c]একটি অনুলিপি করার জন্য কেবল ধীর এবং ভার্জিক উপায় c, তবে আপনি কেন এটি করবেন? দ্বিতীয়ত, আপনার কোড পরিষ্কারভাবে রূপান্তর করতে যাচ্ছে 'APPLE ]['মধ্যে 'APPLE ', কারণ এটি উদ্ধৃত হ্যান্ডেল না, এটি শুধু অনুমান কোন বন্ধনী তালিকা বন্ধনী আছে।
অবতারিত

হা! আপনার মন্তব্যটি যেভাবে আমার কম্পিউটারে ফর্ম্যাট হয়েছে, আমি এমনকি বুঝতে পারি নি যে এটি পুরানো কম্পিউটারগুলিতে প্রকাশিত হওয়ায় অ্যাপল II হওয়ার কথা। যাই হোক না কেন, আপনার উভয় প্রশ্নের আমার উত্তর হ'ল এই অনুশীলনটি - আমার জন্য - কেবল একটি তালিকাকে চাটানোর জন্য একটি সৃজনশীল সমাধান অনুসন্ধানের পরীক্ষা an আমি নিশ্চিত নই যে আমি এখানকার প্রতিটি তালিকা সমতল করার জন্য এটি সাধারণকরণ করব।
মৃত্তিকা

আপনার কেবল প্রয়োজন arr_str = str(arr)এবং তারপর [int(s) for s in re.findall(r'\d+', arr_str)]সত্যই। Github.com/jorgeorpinel/flatten_nested_lists/blob/master/…
জর্জি অরপিনেল

10
def flatten(xs):
    res = []
    def loop(ys):
        for i in ys:
            if isinstance(i, list):
                loop(i)
            else:
                res.append(i)
    loop(xs)
    return res

8

আপনি deepflattenতৃতীয় পক্ষের প্যাকেজ থেকে ব্যবহার করতে পারেন iteration_utilities:

>>> from iteration_utilities import deepflatten
>>> L = [[[1, 2, 3], [4, 5]], 6]
>>> list(deepflatten(L))
[1, 2, 3, 4, 5, 6]

>>> list(deepflatten(L, types=list))  # only flatten "inner" lists
[1, 2, 3, 4, 5, 6]

এটি একটি পুনরাবৃত্তিকারী যাতে আপনার এটি পুনরাবৃত্তি করতে হবে (উদাহরণস্বরূপ এটিকে মোড়ানো listবা একটি লুপে ব্যবহার করে)। অভ্যন্তরীণভাবে এটি পুনরাবৃত্ত পদ্ধতির পরিবর্তে পুনরাবৃত্ত পদ্ধতির ব্যবহার করে এবং এটি সি এক্সটেনশন হিসাবে লেখা হয় যাতে এটি খাঁটি অজগর পদ্ধতির চেয়ে দ্রুততর হতে পারে:

>>> %timeit list(deepflatten(L))
12.6 µs ± 298 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
>>> %timeit list(deepflatten(L, types=list))
8.7 µs ± 139 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

>>> %timeit list(flatten(L))   # Cristian - Python 3.x approach from https://stackoverflow.com/a/2158532/5393381
86.4 µs ± 4.42 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

>>> %timeit list(flatten(L))   # Josh Lee - https://stackoverflow.com/a/2158522/5393381
107 µs ± 2.99 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

>>> %timeit list(genflat(L, list))  # Alex Martelli - https://stackoverflow.com/a/2159079/5393381
23.1 µs ± 710 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

আমি iteration_utilitiesগ্রন্থাগারের লেখক ।


7

পাইথনের অনিয়মিত তালিকাকে সমতল করতে পারে এমন একটি ফাংশন তৈরির চেষ্টা করার বিষয়টি মজাদার ছিল, তবে অবশ্যই পাইথন এটির জন্য (প্রোগ্রামিং মজা করার জন্য)। নিম্নলিখিত জেনারেটর কিছু সাবধানতার সাথে মোটামুটি ভাল কাজ করে:

def flatten(iterable):
    try:
        for item in iterable:
            yield from flatten(item)
    except TypeError:
        yield iterable

এটা তোলে datatypes আপনি একা বাকি চাইতে পারেন যে (মত চেপ্টা হবে bytearray, bytesএবং strবস্তু)। এছাড়াও, কোডটি এই সত্যের উপর নির্ভর করে যে একটি পুনরাবৃত্তযোগ্য থেকে কোনও পুনরুক্তিকারীকে অনুরোধ করা একটি উত্থাপন করে TypeError

>>> L = [[[1, 2, 3], [4, 5]], 6]
>>> def flatten(iterable):
    try:
        for item in iterable:
            yield from flatten(item)
    except TypeError:
        yield iterable


>>> list(flatten(L))
[1, 2, 3, 4, 5, 6]
>>>

সম্পাদনা:

আমি আগের প্রয়োগের সাথে একমত নই। সমস্যাটি হ'ল এমন কোনও জিনিস যা আপনাকে পুনরাবৃত্তিযোগ্য নয় তা সমতল করতে সক্ষম হবে না। এটি বিভ্রান্তিকর এবং যুক্তির ভুল ধারণা দেয়।

>>> list(flatten(123))
[123]
>>>

নিম্নলিখিত জেনারেটরটি প্রায় প্রথম হিসাবে একই তবে একটি পুনরাবৃত্তিযোগ্য অবজেক্টকে সমতল করার চেষ্টা করার সমস্যা নেই। এটি যখন অনুপযুক্ত যুক্তি দেওয়া হয় তখন এটি প্রত্যাশার সাথে ব্যর্থ হয়।

def flatten(iterable):
    for item in iterable:
        try:
            yield from flatten(item)
        except TypeError:
            yield item

জেনারেটরের পরীক্ষা করা যা সরবরাহ করা হয়েছিল সেই তালিকাটির সাথে সূক্ষ্মভাবে কাজ করে। যাইহোক, নতুন কোড একটি উত্থাপন করবে TypeErrorযখন কোনও অ-পুনরাবৃত্তিযোগ্য বস্তু এটি দেওয়া হবে। উদাহরণগুলি নতুন আচরণের নীচে দেখানো হয়েছে।

>>> L = [[[1, 2, 3], [4, 5]], 6]
>>> list(flatten(L))
[1, 2, 3, 4, 5, 6]
>>> list(flatten(123))
Traceback (most recent call last):
  File "<pyshell#32>", line 1, in <module>
    list(flatten(123))
  File "<pyshell#27>", line 2, in flatten
    for item in iterable:
TypeError: 'int' object is not iterable
>>>

5

যদিও একটি মার্জিত এবং খুব পাইথনিক উত্তর নির্বাচন করা হয়েছে আমি আমার সমাধানটি কেবল পর্যালোচনার জন্য উপস্থাপন করব:

def flat(l):
    ret = []
    for i in l:
        if isinstance(i, list) or isinstance(i, tuple):
            ret.extend(flat(i))
        else:
            ret.append(i)
    return ret

দয়া করে বলুন এই কোডটি কতটা ভাল বা খারাপ?


1
ব্যবহার isinstance(i, (tuple, list))। খালি ভেরিয়েবলের সূচনা করা আমার পক্ষে বিকল্প কোড কাঠামো, সাধারণত বোধগম্যতা, জেনারেটর, পুনরাবৃত্তি ইত্যাদির
সন্ধানের

3
return type(l)(ret)আপনি যেমন পাত্রে প্রেরণ করা হয়েছিল ঠিক তেমনই ফিরে আসবে। :)
ড্যাশ-টম-ব্যাং

@ ড্যাশ-টম-ব্যাং আপনি কি দয়া করে কিছুটা বিশদে এটি ব্যাখ্যা করতে পারেন।
34

1
আপনি যদি একটি তালিকায় পাস করেন তবে আপনি সম্ভবত একটি তালিকা ফিরে চান। আপনি যদি একটি টিপলে পাস করেন তবে আপনি সম্ভবত একটি টিপল ফিরে চান। আপনি যদি দু'জনের একটি বিভ্রান্তিতে পাস করেন তবে বাইরের ঘেরের জিনিস যা ছিল তা পেয়ে যাবেন।
ড্যাশ-টম-ব্যাং

4

আমি সহজ উত্তর পছন্দ। কোনও জেনারেটর নেই। কোনও পুনরাবৃত্তি বা পুনরাবৃত্তি সীমা নেই। কেবল পুনরাবৃত্তি:

def flatten(TheList):
    listIsNested = True

    while listIsNested:                 #outer loop
        keepChecking = False
        Temp = []

        for element in TheList:         #inner loop
            if isinstance(element,list):
                Temp.extend(element)
                keepChecking = True
            else:
                Temp.append(element)

        listIsNested = keepChecking     #determine if outer loop exits
        TheList = Temp[:]

    return TheList

এটি দুটি তালিকার সাথে কাজ করে: লুপের জন্য একটি অভ্যন্তরীণ এবং লুপের জন্য একটি বাহ্যিক।

লুপের জন্য অভ্যন্তর তালিকাটির মাধ্যমে পুনরাবৃত্তি করে। যদি এটি একটি তালিকার উপাদান খুঁজে পায়, তবে এটি (1) নেস্টিংয়ের সেই অংশটি সমতল করার জন্য list.extend () ব্যবহার করে এবং (২) সত্য থেকে চেক করে রাখে। লুপের সময় বাইরের নিয়ন্ত্রণের জন্য কিপ চেকিং ব্যবহৃত হয়। যদি বাইরের লুপটি সত্যে সেট হয়ে যায়, এটি অন্য পাসের জন্য অভ্যন্তরীণ লুপটিকে ট্রিগার করে।

আর কোনও নেস্টেড তালিকা না পাওয়া পর্যন্ত এই পাসগুলি ঘটতে থাকে। যখন শেষ পর্যন্ত কোনও পাস পাওয়া যায় যেখানে কিছুই পাওয়া যায় না, কেপচেকিং কখনই সত্যে বিভ্রান্ত হয় না, যার অর্থ তালিকার তালিকা নিখরচায় থাকে এবং বাহিরের বাইরে যখন লুপ বের হয়।

সমতল তালিকাটি ফেরত দেওয়া হয়।

টেস্ট রানের

flatten([1,2,3,4,[100,200,300,[1000,2000,3000]]])

[1, 2, 3, 4, 100, 200, 300, 1000, 2000, 3000]


আমি খুব সহজ। এই ক্ষেত্রে যদিও, আপনি নীড় বা স্তরের স্তর যতবার আছে তালিকার উপরে পুনরাবৃত্তি। ব্যয়বহুল পেতে পারে।
টেলিওট 99

@ টেলিওট৯৯: আপনার তালিকাগুলি যদি সত্যিই বড় এবং / অথবা বড় গভীরতায় নেস্ট করে থাকে তবে আপনি ঠিক বলেছেন। যাইহোক, যদি এটি না হয়, তবে সহজ সমাধান ঠিক একইভাবে কাজ করে এবং অন্যান্য উত্তরগুলির গভীর জাদু ছাড়াই। মাল্টি-স্টেজ রিকার্সিভ জেনারেটর বোঝার জন্য একটি জায়গা রয়েছে তবে আমি নিশ্চিত নই যে আপনি যেখানে প্রথম দেখবেন সেটাই হওয়া উচিত। (আমি অনুমান করি আপনি কোথায় জানেন "ওয়ার্স ইজ বেটার" বিতর্কে আমি কোথায় পড়েছি))
কাদামাটি

@ টেলিওট৯৯: বা অন্য কোনও উপায়ে বলতে গেলে আমার সমাধানকে "গ্রুকের চেষ্টা" করতে হবে না। যদি পারফরম্যান্স কোনও বাধা না হয় তবে প্রোগ্রামার হিসাবে আপনার কাছে সবচেয়ে বেশি কী গুরুত্বপূর্ণ?
কাদামাটি

সহজ সমাধানগুলিতে কম যুক্তি রয়েছে। পুনরাবৃত্তি একটি দুর্দান্ত মৌলিক প্রোগ্রামিং কনস্ট্রাক্ট যা নিজেকে প্রোগ্রামার হিসাবে বিবেচনা করে যে কেউ তার সাথে পুরোপুরি আরামদায়ক হওয়া উচিত। জেনারেটরগুলি পাইথন ওয়ে খুব বেশি এবং (বোধগম্যতার সাথে) এমন কিছু যা কোনও পেশাদার পাইথন প্রোগ্রামারকে তাত্ক্ষণিকভাবে ছাঁটাই করা উচিত।
ড্যাশ-টম-ব্যাং

1
আমি পুনরাবৃত্তি সম্পর্কে একমত। আমি যখন আমার উত্তরটি লিখেছিলাম তখন অজগরটি এখনও 1000 চক্রের পুনরাবৃত্তি ভাঙল। তারা কি এই পরিবর্তন করেছে? পেশাদার পাইথন প্রোগ্রামার হিসাবে, আমি না। তদুপরি, আমি কল্পনা করি অজুতে প্রোগ্রামিং করা অনেকেই পুরো সময়টি করেন না।
কাদামাটি

4

এখানে একটি সাধারণ ফাংশন যা স্বেচ্ছাসেবী গভীরতার তালিকাগুলিকে সমতল করে। স্ট্যাক ওভারফ্লো এড়ানোর জন্য কোনও পুনরাবৃত্তি নেই।

from copy import deepcopy

def flatten_list(nested_list):
    """Flatten an arbitrarily nested list, without recursion (to avoid
    stack overflows). Returns a new list, the original list is unchanged.

    >> list(flatten_list([1, 2, 3, [4], [], [[[[[[[[[5]]]]]]]]]]))
    [1, 2, 3, 4, 5]
    >> list(flatten_list([[1, 2], 3]))
    [1, 2, 3]

    """
    nested_list = deepcopy(nested_list)

    while nested_list:
        sublist = nested_list.pop(0)

        if isinstance(sublist, list):
            nested_list = sublist + nested_list
        else:
            yield sublist


3

আমি অবাক হয়েছি কেউ এ নিয়ে ভাবেনি। অভিশাপ পুনরাবৃত্তি আমি এখানকার উন্নত লোকেরা পুনরাবৃত্ত উত্তরগুলি পাই না। যাইহোক এখানে এই আমার চেষ্টা। সতর্কতা এটি ওপি-র ব্যবহারের ক্ষেত্রে খুব নির্দিষ্ট

import re

L = [[[1, 2, 3], [4, 5]], 6]
flattened_list = re.sub("[\[\]]", "", str(L)).replace(" ", "").split(",")
new_list = list(map(int, flattened_list))
print(new_list)

আউটপুট:

[1, 2, 3, 4, 5, 6]

3

আমি এখানে ইতিমধ্যে উপলব্ধ সমস্ত উত্তর দিয়ে যাইনি, তবে এখানে লিস্পের প্রথম এবং বিশ্রামের তালিকা প্রক্রিয়াকরণের উপায় থেকে ধার করে আমি এক লাইনার নিয়ে এসেছি

def flatten(l): return flatten(l[0]) + (flatten(l[1:]) if len(l) > 1 else []) if type(l) is list else [l]

এখানে একটি সহজ এবং একটি সহজ-সরল কেস নেই -

>>> flatten([1,[2,3],4])
[1, 2, 3, 4]

>>> flatten([1, [2, 3], 4, [5, [6, {'name': 'some_name', 'age':30}, 7]], [8, 9, [10, [11, [12, [13, {'some', 'set'}, 14, [15, 'some_string'], 16], 17, 18], 19], 20], 21, 22, [23, 24], 25], 26, 27, 28, 29, 30])
[1, 2, 3, 4, 5, 6, {'age': 30, 'name': 'some_name'}, 7, 8, 9, 10, 11, 12, 13, set(['set', 'some']), 14, 15, 'some_string', 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
>>> 

এটি ওয়ান লাইনার নয়। আপনি এটির মধ্যে কতটা ফিট করার চেষ্টা করুন না কেন, এটি def foo():একটি আলাদা লাইন। এছাড়াও, এটি খুব অপঠনযোগ্য।
সিএস 95

আমি কোডটি ডি-ও-লাইন-আইফাইড করেছি এবং আরও কিছু সংশোধনকারী করেছি। (সম্পাদনাটি সমীকরণের পর্যালোচনা মুলতুবি হিসাবে আমি লিখছি) এই বিশেষ পদ্ধতিটি আমার কাছে খুব পঠনযোগ্য বলে মনে হয়েছিল, যদিও মূল কোডটিতে কিছু রিফ্যাক্টরিং দরকার ছিল।
এমিলিও এম বুমাচার

3

এই জাতীয় প্রশ্নের উত্তর দেওয়ার চেষ্টা করার সময় আপনার সমাধান হিসাবে প্রস্তাবিত কোডটির সীমাবদ্ধতা দেওয়া উচিত। এটি যদি কেবল পারফরম্যান্স সম্পর্কে হয় তবে আমি খুব বেশি কিছু মনে করব না, তবে সমাধান হিসাবে প্রস্তাবিত বেশিরভাগ কোড (স্বীকৃত উত্তর সহ) 1000 এরও বেশি গভীরতার কোনও তালিকা সমতল করতে ব্যর্থ।

যখন আমি বেশিরভাগ কোড বলি অর্থ এমন সমস্ত কোড যা পুনরাবৃত্তির কোনও ফর্ম ব্যবহার করে (বা পুনরাবৃত্ত হওয়া কোনও স্ট্যান্ডার্ড লাইব্রেরি ফাংশনকে কল করে)। এই সমস্ত কোডগুলি ব্যর্থ হয়েছে কারণ প্রত্যেকটি পুনরাবৃত্ত কল করার জন্য, (কল) স্ট্যাকটি এক ইউনিট দ্বারা বৃদ্ধি পায় এবং (ডিফল্ট) পাইথন কল স্ট্যাকের আকার 1000 থাকে।

আপনি যদি কল স্ট্যাকের সাথে খুব বেশি পরিচিত না হন, তবে নীচেরগুলি সম্ভবত সহায়তা করবে (অন্যথায় আপনি কেবল বাস্তবায়নে স্ক্রোল করতে পারেন) )।

স্ট্যাক আকার এবং পুনরাবৃত্ত প্রোগ্রামিং কল (অন্ধকূপ সাদৃশ্য)

ধন সন্ধান এবং প্রস্থান

কল্পনা করুন যে আপনি সংখ্যাযুক্ত কক্ষগুলি সহ একটি বিশাল অন্ধকার প্রবেশ করিয়া একটি ধন সন্ধান করছেন। আপনি জায়গাটি জানেন না তবে কীভাবে ধন সন্ধান করবেন তা সম্পর্কে আপনার কাছে কিছু ইঙ্গিত রয়েছে। প্রতিটি ইঙ্গিত একটি ধাঁধা (অসুবিধা পরিবর্তিত হয়, তবে তারা কতটা কঠোর হবে তা আপনি অনুমান করতে পারবেন না)। সময় বাঁচানোর কৌশল সম্পর্কে আপনি কিছুটা চিন্তা করার সিদ্ধান্ত নিয়েছেন, আপনি দুটি পর্যবেক্ষণ করেছেন:

  1. ধন খুঁজে পাওয়া শক্ত (দীর্ঘ) কারণ আপনাকে সেখানে পৌঁছানোর জন্য (সম্ভাব্য শক্ত) ধাঁধাগুলি সমাধান করতে হবে।
  2. একবার ধনটি পাওয়া গেলে প্রবেশদ্বারে ফিরে আসা সহজ হতে পারে, আপনাকে কেবল একই দিকে অন্য দিকে ব্যবহার করতে হবে (যদিও আপনার পথটি স্মরণ করতে এটির জন্য কিছুটা স্মৃতি দরকার)।

অন্ধকূপ প্রবেশ করার সময়, আপনি এখানে একটি ছোট নোটবুক লক্ষ্য করুন। আপনি একটি ধাঁধা সমাধানের পরে আপনি যে কক্ষটি বেরোবেন তার প্রতিটি ঘর লিখতে ব্যবহার করার সিদ্ধান্ত নেন (নতুন ঘরে প্রবেশের সময়), আপনি প্রবেশদ্বারে ফিরে যেতে সক্ষম হবেন। এটি একটি প্রতিভা ধারণা, আপনি নিজের কৌশল বাস্তবায়নের জন্য এক শতাংশও ব্যয় করবেন না

আপনি প্রথম 1001 ধাঁধাটি দুর্দান্ত সাফল্যের সাথে সমাধান করে অন্ধকূপে প্রবেশ করুন, তবে এখানে এমন কিছু আসে যা আপনি প্ল্যান করেননি, আপনার নেওয়া নোটবুকটিতে আপনার কোনও স্থান নেই। অন্ধকূপের অভ্যন্তরে চিরতরে হারিয়ে যাওয়ার চেয়ে ধন না পাওয়া পছন্দ করার কারণে আপনি আপনার অনুসন্ধান ত্যাগ করার সিদ্ধান্ত নিয়েছেন (এটি সত্যই স্মার্ট দেখাচ্ছে)।

একটি পুনরাবৃত্তি প্রোগ্রাম কার্যকর করা হচ্ছে

মূলত, এটি ধন খুঁজে পাওয়ার মতো একই জিনিস। অন্ধকূপ হয় কম্পিউটার এর মেমরি , আপনার লক্ষ্য এখন একটি ধন খুঁজে পেতে কিন্তু হয় কিছু ফাংশন গনা (খোঁজ চ (x) এর জন্য একটি প্রদত্ত এক্স )। ইঙ্গিতগুলি কেবলমাত্র সাব-রুটিন যা আপনাকে f (x) সমাধান করতে সহায়তা করবে । আপনার কৌশলটি কল স্ট্যাক কৌশল হিসাবে একই , নোটবুকটি স্ট্যাক, ঘরগুলি ফাংশনের রিটার্ন ঠিকানাগুলি:

x = ["over here", "am", "I"]
y = sorted(x) # You're about to enter a room named `sorted`, note down the current room address here so you can return back: 0x4004f4 (that room address looks weird)
# Seems like you went back from your quest using the return address 0x4004f4
# Let's see what you've collected 
print(' '.join(y))

অন্ধকূপে আপনি যে সমস্যার মুখোমুখি হয়েছিলেন তা এখানে একই রকম হবে, কল স্ট্যাকের একটি সীমাবদ্ধ আকার রয়েছে (এখানে 1000) এবং তাই, যদি আপনি ফিরে না ফিরে অনেকগুলি ফাংশন প্রবেশ করেন তবে আপনি কল স্ট্যাকটি পূরণ করবেন এবং দেখতে ত্রুটিযুক্ত হবে "প্রিয় অ্যাডভেঞ্চারার, : যেমন আমি খুব দুঃখিত তবে আপনার নোটবুকটি পূর্ণ" যা একবারে নিজেকে কল করে - বারবার -) আপনি গণনা শেষ না হওয়া অবধি উপরে প্রবেশ করবেন এবং (ধন সন্ধান না হওয়া পর্যন্ত ) ফিরে আসবেন আপনি যেখানে প্রথম স্থানে ডেকেছিলেন সেখানে ফিরে যান । কল স্ট্যাক কখনই কোনও কিছুর হাত থেকে মুক্ত হবে না যেখানে এটি একের পর এক সমস্ত রিটার্ন ঠিকানা থেকে মুক্ত হবে।RecursionError: maximum recursion depth exceeded । মনে রাখবেন যে কল স্ট্যাকটি পূরণ করার জন্য আপনার পুনরাবৃত্তি প্রয়োজন হবে না, তবে কোনও পুনঃবিবর্তনযোগ্য প্রোগ্রাম কখনও না ফিরে 1000 ফাংশনগুলিতে কল করে। এটি বুঝতেও গুরুত্বপূর্ণ যে একবার আপনি কোনও ফাংশন থেকে ফিরে আসার পরে, কল স্ট্যাকটি ব্যবহার করা ঠিকানা থেকে মুক্ত করা হবে (সুতরাং "স্ট্যাক" নামটি নাম, কোনও ফাংশনে প্রবেশের আগে ফেরতের ঠিকানাটি পুশ করা হয় এবং ফিরে আসার সময় টানিয়ে দেওয়া হয়)। একটি সাধারণ পুনরাবৃত্তি (একটি ফাংশন) এর বিশেষ ক্ষেত্রেffff

কীভাবে এই সমস্যা এড়ানো যায়?

এটি আসলে খুব সহজ: "আপনি যদি না জানেন যে এটি কত গভীরভাবে যেতে পারে তবে পুনরাবৃত্তি ব্যবহার করবেন না"। এটি কিছু ক্ষেত্রে যেমন সর্বদা সত্য হয় না, টেল কল পুনরাবৃত্তি অপ্টিমাইজড (টিসিও) হতে পারে । কিন্তু অজগর ক্ষেত্রে, এটি কেস নয়, এমনকি "ভাল লিখিত" পুনরাবৃত্ত ফাংশন স্ট্যাকের ব্যবহারকে অনুকূলিত করবে না । এই প্রশ্নটি সম্পর্কে গিডোর একটি আকর্ষণীয় পোস্ট রয়েছে: টেল রিকার্সন ইলিমিনেশন

এমন একটি প্রযুক্তি রয়েছে যা আপনি কোনও পুনরাবৃত্ত ফাংশন পুনরাবৃত্তি করতে ব্যবহার করতে পারেন, এই কৌশলটি আমরা আপনার নিজস্ব নোটবুক আনতে কল করতে পারি । উদাহরণস্বরূপ, আমাদের বিশেষ ক্ষেত্রে আমরা কেবল একটি তালিকা অন্বেষণ করছি, একটি ঘরে প্রবেশ করা একটি সাবলিস্টে প্রবেশের সমতুল্য, আপনার নিজের প্রশ্নটি জিজ্ঞাসা করা উচিত আমি কীভাবে তালিকা থেকে তার পিতামাতার তালিকায় ফিরে আসতে পারি? উত্তরটি এত জটিল নয়, stackখালি থাকা পর্যন্ত নিম্নলিখিতটি পুনরাবৃত্তি করুন :

  1. বর্তমান তালিকায় ধাক্কা addressএবং indexএকটি stackএকটি নতুন sublist প্রবেশ (নোট একটি তালিকা ঠিকানা + + সূচক এছাড়াও একটি ঠিকানা যে, এর ফলে আমরা শুধু কল স্ট্যাক দ্বারা ব্যবহৃত সঠিক একই কৌশল ব্যবহার);
  2. প্রতিবার কোনও আইটেম পাওয়া গেলে yieldএটি (বা এগুলিকে একটি তালিকায় যুক্ত করুন);
  3. একবার একটি তালিকা সম্পূর্ণরূপে অন্বেষণ করা হয়, ব্যবহার পিতা বা মাতা তালিকা ফিরে যেতে stack প্রত্যাবর্তন address(এবং index)

আরও মনে রাখবেন যে এটি এমন গাছের ডিএফএসের সমতুল্য যেখানে কয়েকটি নোড সাবলিস্ট A = [1, 2]এবং কিছু সাধারণ আইটেম: 0, 1, 2, 3, 4(জন্য L = [0, [1,2], 3, 4])। গাছটি দেখতে এরকম দেখাচ্ছে:

                    L
                    |
           -------------------
           |     |     |     |
           0   --A--   3     4
               |   |
               1   2

ডিএফএসের ট্র্যাভারসাল প্রাক অর্ডারটি হ'ল: এল, 0, এ, 1, 2, 3, 4 Remember মনে রাখবেন, পুনরাবৃত্ত ডিএফএস বাস্তবায়নের জন্য আপনাকে একটি স্ট্যাকেরও "প্রয়োজন" রয়েছে। নীচের রাজ্যগুলির (এবং stackএবং এর জন্য flat_list) ফলাফলের আগে আমি প্রয়োগের প্রস্তাব দিয়েছিলাম :

init.:  stack=[(L, 0)]
**0**:  stack=[(L, 0)],         flat_list=[0]
**A**:  stack=[(L, 1), (A, 0)], flat_list=[0]
**1**:  stack=[(L, 1), (A, 0)], flat_list=[0, 1]
**2**:  stack=[(L, 1), (A, 1)], flat_list=[0, 1, 2]
**3**:  stack=[(L, 2)],         flat_list=[0, 1, 2, 3]
**3**:  stack=[(L, 3)],         flat_list=[0, 1, 2, 3, 4]
return: stack=[],               flat_list=[0, 1, 2, 3, 4]

এই উদাহরণে, স্ট্যাকের সর্বোচ্চ আকার 2, কারণ ইনপুট তালিকার (এবং তাই গাছের) গভীরতা 2 রয়েছে।

বাস্তবায়ন

বাস্তবায়নের জন্য, পাইথনে আপনি সাধারণ তালিকার পরিবর্তে পুনরাবৃত্তি ব্যবহার করে কিছুটা সহজ করতে পারেন। (উপ) পুনরুক্তিগুলির রেফারেন্সগুলি সাবলিস্টগুলি রিটার্ন ঠিকানাগুলি (তালিকার ঠিকানা এবং সূচক উভয়ের পরিবর্তে ) সংরক্ষণ করার জন্য ব্যবহৃত হবে । এটি কোনও বড় পার্থক্য নয় তবে আমি মনে করি এটি আরও পঠনযোগ্য (এবং কিছুটা দ্রুত):

def flatten(iterable):
    return list(items_from(iterable))

def items_from(iterable):
    cursor_stack = [iter(iterable)]
    while cursor_stack:
        sub_iterable = cursor_stack[-1]
        try:
            item = next(sub_iterable)
        except StopIteration:   # post-order
            cursor_stack.pop()
            continue
        if is_list_like(item):  # pre-order
            cursor_stack.append(iter(item))
        elif item is not None:
            yield item          # in-order

def is_list_like(item):
    return isinstance(item, list)

এছাড়াও, খেয়াল করুন যে is_list_likeআমার মধ্যে isinstance(item, list), যা আরও ইনপুট ধরণের হ্যান্ডেল করার জন্য পরিবর্তন করা যেতে পারে, এখানে আমি কেবল সাদামাটা সংস্করণটি চেয়েছিলাম যেখানে (পুনরাবৃত্ত) কেবল একটি তালিকা। তবে আপনি এটি করতে পারেন:

def is_list_like(item):
    try:
        iter(item)
        return not isinstance(item, str)  # strings are not lists (hmm...) 
    except TypeError:
        return False

এটি স্ট্রিংগুলিকে "সরল আইটেম" হিসাবে বিবেচনা করে এবং তাই flatten_iter([["test", "a"], "b])ফিরে আসবে ["test", "a", "b"]এবং হবে না ["t", "e", "s", "t", "a", "b"]। সেক্ষেত্রে মন্তব্য করুন যে, iter(item)প্রতিটি আইটেমটিতে দু'বার ডাকা হয়, আসুন আমরা পাঠককে এই ক্লিনারটি তৈরি করার অনুশীলন করে দেখান।

অন্যান্য প্রয়োগের উপর পরীক্ষা এবং মন্তব্য

শেষ পর্যন্ত, মনে রাখবেন যে আপনি কোনও অনন্ত নেস্টেড তালিকা Lব্যবহার করে মুদ্রণ করতে পারবেন না print(L)কারণ অভ্যন্তরীণভাবে এটি __repr__( RecursionError: maximum recursion depth exceeded while getting the repr of an object) এ পুনরাবৃত্ত কলগুলি ব্যবহার করবে । একই কারণে, flattenজড়িত থাকার সমাধানগুলি strএকই ত্রুটি বার্তার সাথে ব্যর্থ হবে।

আপনার সমাধানটি পরীক্ষা করার দরকার হলে আপনি একটি সহজ নেস্টেড তালিকা তৈরি করতে এই ফাংশনটি ব্যবহার করতে পারেন:

def build_deep_list(depth):
    """Returns a list of the form $l_{depth} = [depth-1, l_{depth-1}]$
    with $depth > 1$ and $l_0 = [0]$.
    """
    sub_list = [0]
    for d in range(1, depth):
        sub_list = [d, sub_list]
    return sub_list

যা দেয়: build_deep_list(5)>>> [4, [3, [2, [1, [0]]]]]


2

এখানে compiler.ast.flattenবাস্তবায়ন ২.7.৫:

def flatten(seq):
    l = []
    for elt in seq:
        t = type(elt)
        if t is tuple or t is list:
            for elt2 in flatten(elt):
                l.append(elt2)
        else:
            l.append(elt)
    return l

আরও ভাল, দ্রুততর পদ্ধতি রয়েছে (আপনি যদি এখানে পৌঁছে থাকেন তবে আপনি সেগুলি ইতিমধ্যে দেখে ফেলেছেন)

আরও মনে রাখবেন:

সংস্করণ ২.6 থেকে হ্রাস করা: পাইথন 3-এ সংকলক প্যাকেজটি সরানো হয়েছে।


2

সম্পূর্ণরূপে হ্যাকি তবে আমি মনে করি এটি কার্যকর হবে (আপনার ডেটা_ টাইপের উপর নির্ভর করে)

flat_list = ast.literal_eval("[%s]"%re.sub("[\[\]]","",str(the_list)))

2

কেবল একটি funcyলাইব্রেরি ব্যবহার করুন : pip install funcy

import funcy


funcy.flatten([[[[1, 1], 1], 2], 3]) # returns generator
funcy.lflatten([[[[1, 1], 1], 2], 3]) # returns list

1
এফওয়াইআই: এটি পুনরাবৃত্ত সমাধানগুলি ব্যবহার করে: উত্সের লিঙ্ক
জর্জি

1

এখানে আরেকটি পাই 2 পদ্ধতি রয়েছে, আমি নিশ্চিত নই যে এটির দ্রুততম বা সর্বাধিক মার্জিত বা নিরাপদ কিনা ...

from collections import Iterable
from itertools import imap, repeat, chain


def flat(seqs, ignore=(int, long, float, basestring)):
    return repeat(seqs, 1) if any(imap(isinstance, repeat(seqs), ignore)) or not isinstance(seqs, Iterable) else chain.from_iterable(imap(flat, seqs))

এটি আপনার পছন্দ মতো কোনও নির্দিষ্ট (বা উত্পন্ন) ধরণের উপেক্ষা করতে পারে, এটি একটি পুনরুক্তি ফেরত দেয়, তাই আপনি এটিকে কোনও নির্দিষ্ট পাত্রে যেমন তালিকা, টুপল, ডিকের মধ্যে রূপান্তর করতে পারেন বা ভাল বা খারাপের জন্য স্মৃতি পদক্ষেপের হ্রাস করতে কেবল এটি ব্যবহার করতে পারেন এটি প্রাথমিক অ-পুনরাবৃত্তিযোগ্য অবজেক্টগুলি যেমন ইন্ট ...

নোট করুন বেশিরভাগ ভারী উত্তোলন সি-তে করা হয়, যেহেতু আমি জানি যতদূর ইয়ারটোলগুলি কীভাবে প্রয়োগ করা হয়, তাই এটি পুনরাবৃত্ত হওয়ার সময়, আফ্রিক এটি সিটিতে অজগর পুনরাবৃত্তির গভীরতায় আবদ্ধ হয় না, যদিও এটি ফাংশন কলগুলি সি তে ঘটছে, যদিও এটি এর অর্থ এই নয় যে আপনি স্মৃতি দ্বারা আবদ্ধ, বিশেষত ওএস এক্সে যেখানে এর স্ট্যাকের আকারের আজকের হিসাবে একটি হার্ড সীমা রয়েছে (ওএস এক্স মাভারিক্স) ...

কিছুটা দ্রুত পন্থা রয়েছে, তবে কম পোর্টেবল পদ্ধতি কেবলমাত্র এটি ব্যবহার করুন আপনি যদি অনুমান করতে পারেন যে ইনপুটটির মূল উপাদানগুলি স্পষ্টভাবে নির্ধারণ করা যেতে পারে অন্যথায়, আপনি একটি অসীম পুনরাবৃত্তি পাবেন এবং ওএস এক্স এর সীমিত স্ট্যাক আকারের সাথে, মোটামুটি দ্রুত একটি সেগমেন্টেশন ত্রুটি নিক্ষেপ করুন ...

def flat(seqs, ignore={int, long, float, str, unicode}):
    return repeat(seqs, 1) if type(seqs) in ignore or not isinstance(seqs, Iterable) else chain.from_iterable(imap(flat, seqs))

এখানে আমরা প্রকারটি পরীক্ষা করার জন্য সেটগুলি ব্যবহার করছি যাতে কোনও উপাদানকে উপেক্ষা করা উচিত কিনা তা পরীক্ষা করতে ও (1) বনাম ও (ধরণের সংখ্যা) লাগে, যদিও অবশ্যই বর্ণিত উপেক্ষা করা ধরণের উদ্ভূত প্রকারের কোনও মান ব্যর্থ হবে , এই কারণেই এটি ব্যবহার করে str,unicode সুতরাং এটি সাবধানতার সাথে ব্যবহার করুন ...

পরীক্ষা:

import random

def test_flat(test_size=2000):
    def increase_depth(value, depth=1):
        for func in xrange(depth):
            value = repeat(value, 1)
        return value

    def random_sub_chaining(nested_values):
        for values in nested_values:
            yield chain((values,), chain.from_iterable(imap(next, repeat(nested_values, random.randint(1, 10)))))

    expected_values = zip(xrange(test_size), imap(str, xrange(test_size)))
    nested_values = random_sub_chaining((increase_depth(value, depth) for depth, value in enumerate(expected_values)))
    assert not any(imap(cmp, chain.from_iterable(expected_values), flat(chain(((),), nested_values, ((),)))))

>>> test_flat()
>>> list(flat([[[1, 2, 3], [4, 5]], 6]))
[1, 2, 3, 4, 5, 6]
>>>  

$ uname -a
Darwin Samys-MacBook-Pro.local 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun  3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64
$ python --version
Python 2.7.5

1

কোনও লাইব্রেরি ব্যবহার না করে:

def flat(l):
    def _flat(l, r):    
        if type(l) is not list:
            r.append(l)
        else:
            for i in l:
                r = r + flat(i)
        return r
    return _flat(l, [])



# example
test = [[1], [[2]], [3], [['a','b','c'] , [['z','x','y']], ['d','f','g']], 4]    
print flat(test) # prints [1, 2, 3, 'a', 'b', 'c', 'z', 'x', 'y', 'd', 'f', 'g', 4]

1

ব্যবহার itertools.chain:

import itertools
from collections import Iterable

def list_flatten(lst):
    flat_lst = []
    for item in itertools.chain(lst):
        if isinstance(item, Iterable):
            item = list_flatten(item)
            flat_lst.extend(item)
        else:
            flat_lst.append(item)
    return flat_lst

বা শিকল ছাড়াই:

def flatten(q, final):
    if not q:
        return
    if isinstance(q, list):
        if not isinstance(q[0], list):
            final.append(q[0])
        else:
            flatten(q[0], final)
        flatten(q[1:], final)
    else:
        final.append(q)

1

আমি কোনও গভীরতার সাথে নেস্টেড তালিকা সমাধান করতে পুনরাবৃত্ত ব্যবহার করেছি

def combine_nlist(nlist,init=0,combiner=lambda x,y: x+y):
    '''
    apply function: combiner to a nested list element by element(treated as flatten list)
    '''
    current_value=init
    for each_item in nlist:
        if isinstance(each_item,list):
            current_value =combine_nlist(each_item,current_value,combiner)
        else:
            current_value = combiner(current_value,each_item)
    return current_value

সুতরাং আমি ফাংশন সংশ্লেষ_নিস্টিফ্ট সংজ্ঞায়িত করার পরে, এই ফাংশনটি করে ফ্ল্যাটিং করা সহজ। অথবা আপনি এটি একটি ফাংশনে একত্রিত করতে পারেন। আমি আমার সমাধানটি পছন্দ করি কারণ এটি কোনও নেস্টেড তালিকায় প্রয়োগ করা যেতে পারে।

def flatten_nlist(nlist):
    return combine_nlist(nlist,[],lambda x,y:x+[y])

ফলাফল

In [379]: flatten_nlist([1,2,3,[4,5],[6],[[[7],8],9],10])
Out[379]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

"কোনও গভীরতার সাথে নেস্টেড তালিকা" সত্য নয়। আপনি current_value = combiner(current_value,each_item) RecursionError: maximum recursion depth exceeded
যাচাই করে

হুঁম আমি কি 1000 টিরও বেশি স্তর দিয়ে তালিকা ফ্ল্যাট করার চেষ্টা করছি?
Oldyoung

অবশ্যই, এটি পুনরাবৃত্ত বনাম পুনরাবৃত্ত সমাধানগুলি সম্পর্কে আলোচনার পুরো বিষয়টি। আপনি যদি আগেই জানেন যে স্তরগুলির সংখ্যা <1000 এর চেয়ে বেশি তবে সবচেয়ে সহজ সমাধানটি কাজ করবে। আপনি যখন "যে কোনও গভীরতা" বলছেন এতে গভীরতার> 1000 এর তালিকা অন্তর্ভুক্ত রয়েছে
সিগলেসেট

1

সবচেয়ে সহজ উপায় হ'ল মোর্ফ লাইব্রেরিটি ব্যবহার করে ব্যবহার করা pip install morph

কোডটি হ'ল:

import morph

list = [[[1, 2, 3], [4, 5]], 6]
flattened_list = morph.flatten(list)  # returns [1, 2, 3, 4, 5, 6]

1

আমি সচেতন যে ইতিমধ্যে অনেক দুর্দান্ত উত্তর রয়েছে তবে আমি একটি উত্তর যুক্ত করতে চেয়েছিলাম যা প্রশ্ন সমাধানের কার্যকরী প্রোগ্রামিং পদ্ধতি ব্যবহার করে। এই উত্তরে আমি দ্বিগুণ পুনরাবৃত্তি ব্যবহার করি:

def flatten_list(seq):
    if not seq:
        return []
    elif isinstance(seq[0],list):
        return (flatten_list(seq[0])+flatten_list(seq[1:]))
    else:
        return [seq[0]]+flatten_list(seq[1:])

print(flatten_list([1,2,[3,[4],5],[6,7]]))

আউটপুট:

[1, 2, 3, 4, 5, 6, 7]

1

আমি নিশ্চিত নই যে এটি অগত্যা দ্রুত বা আরও কার্যকর কিনা, তবে আমি এটি করি:

def flatten(lst):
    return eval('[' + str(lst).replace('[', '').replace(']', '') + ']')

L = [[[1, 2, 3], [4, 5]], 6]
print(flatten(L))

এখানে flattenফাংশন তালিকাটিকে একটি স্ট্রিংয়ে পরিণত করে, সমস্ত বর্গাকার বন্ধনীগুলি বের করে, বর্গাকার বন্ধনীগুলি প্রান্তে আবার সংযুক্ত করে, এবং এটি আবার তালিকায় পরিণত করে।

যদিও, আপনি যদি জানতেন আপনার তালিকায় স্ট্রিংয়ের মতো বর্গাকার বন্ধনী থাকবে, যেমন [[1, 2], "[3, 4] and [5]"], আপনাকে অন্য কিছু করতে হবে।


এটি সহজ সমাধানের চেয়ে কোনও সুবিধা পাবে না কারণ এটি গভীর তালিকাগুলি প্রক্রিয়া করতে ব্যর্থ হয়, অর্থাত "পুনরাবৃত্তির ত্রুটি: কোনও বস্তুর পুনঃনির্মাণ পাওয়ার সময় সর্বাধিক পুনরাবৃত্তির গভীরতা অতিক্রম করে"।
সিগ্লেসেট

1

পাইথন 2 এ এটি ফ্ল্যাটনের একটি সহজ বাস্তবায়ন

flatten=lambda l: reduce(lambda x,y:x+y,map(flatten,l),[]) if isinstance(l,list) else [l]

test=[[1,2,3,[3,4,5],[6,7,[8,9,[10,[11,[12,13,14]]]]]],]
print flatten(test)

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

1

এটি একটি তালিকা বা অভিধান (বা তালিকাগুলির তালিকা বা অভিধানের অভিধান ইত্যাদি) সমতল করবে। এটি ধরে নেওয়া হয় যে মানগুলি স্ট্রিং এবং এটি একটি স্ট্রিং তৈরি করে যা প্রতিটি আইটেমকে পৃথককারী যুক্তির সাথে যুক্ত করে। যদি আপনি চান আপনি বিভাজক ব্যবহার করে ফলাফলটিকে তালিকার অবজেক্টে ভাগ করতে পারেন ward এটি পুনরুক্তি ব্যবহার করে যদি পরবর্তী মানটি তালিকা বা স্ট্রিং হয়। আপনি কী কী যুক্তিটি ব্যবহার করতে পারেন তা বা অভিধানের অবজেক্ট থেকে কীগুলি বা মানগুলি (মিথ্যাতে সেট করুন) চান কিনা তা বলার জন্য।

def flatten_obj(n_obj, key=True, my_sep=''):
    my_string = ''
    if type(n_obj) == list:
        for val in n_obj:
            my_sep_setter = my_sep if my_string != '' else ''
            if type(val) == list or type(val) == dict:
                my_string += my_sep_setter + flatten_obj(val, key, my_sep)
            else:
                my_string += my_sep_setter + val
    elif type(n_obj) == dict:
        for k, v in n_obj.items():
            my_sep_setter = my_sep if my_string != '' else ''
            d_val = k if key else v
            if type(v) == list or type(v) == dict:
                my_string += my_sep_setter + flatten_obj(v, key, my_sep)
            else:
                my_string += my_sep_setter + d_val
    elif type(n_obj) == str:
        my_sep_setter = my_sep if my_string != '' else ''
        my_string += my_sep_setter + n_obj
        return my_string
    return my_string

print(flatten_obj(['just', 'a', ['test', 'to', 'try'], 'right', 'now', ['or', 'later', 'today'],
                [{'dictionary_test': 'test'}, {'dictionary_test_two': 'later_today'}, 'my power is 9000']], my_sep=', ')

উৎপাদনের:

just, a, test, to, try, right, now, or, later, today, dictionary_test, dictionary_test_two, my power is 9000

0

আপনি যদি পুনরাবৃত্তি পছন্দ করেন তবে এটি আপনার আগ্রহের সমাধান হতে পারে:

def f(E):
    if E==[]: 
        return []
    elif type(E) != list: 
        return [E]
    else:
        a = f(E[0])
        b = f(E[1:])
        a.extend(b)
        return a

আমি আসলে কিছু অনুশীলন স্কিম কোড থেকে এটিকে রূপান্তর করেছি যা আমি কিছুক্ষণ আগে লিখেছিলাম।

উপভোগ করুন!


0

আমি অজগর থেকে নতুন এবং লিসপ ব্যাকগ্রাউন্ড থেকে এসেছি। এটিই আমি নিয়ে এসেছি (লুলজের বিভিন্ন নাম দেখুন):

def flatten(lst):
    if lst:
        car,*cdr=lst
        if isinstance(car,(list,tuple)):
            if cdr: return flatten(car) + flatten(cdr)
            return flatten(car)
        if cdr: return [car] + flatten(cdr)
        return [car]

কাজ মনে হচ্ছে। টেস্ট:

flatten((1,2,3,(4,5,6,(7,8,(((1,2)))))))

আয়:

[1, 2, 3, 4, 5, 6, 7, 8, 1, 2]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.