سؤال

Let's say I have a list:

x = ['abc', 'd', 'efgh']

I am trying to create a function so that its desired output would return:

a d e b f c g h

Which is essentially taking the first characters of each element and then skipping onto the next element if there is no index in that area.

Is there an alternative way of doing this w/o using itertools or the zip function?

I tried doing:

for i in x:
      print(i[0], i[1], i[2]....etc)

But that only gives me an error since the second element of the list exceeds the range.

Thank you!

هل كانت مفيدة؟

المحلول

Sure... Take a close look and try to understand what is going on here...

out = []
biggest = max(len(item) for item in x)
for i in range(biggest):
    for item in x:
        if len(item) > i:
            out.append(item[i])

rather than out, I would consider yield to return the items in a generator.

نصائح أخرى

Use the roundrobin recipe from itertools:

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    pending = len(iterables)
    nexts = cycle(iter(it).next for it in iterables)
    while pending:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))

Demo:

>>> x = ['abc', 'd', 'efgh']
>>> from itertools import cycle, islice
>>> list(roundrobin(*x))
['a', 'd', 'e', 'b', 'f', 'c', 'g', 'h']

Another option is to use itertools.izip_longest and itertools.chain.from_iterable:

>>> from itertools import izip_longest, chain
>>> x = ['abc', 'd', 'efgh']
>>> sentinel = object()
>>> [y for y in chain.from_iterable(izip_longest(*x, fillvalue=sentinel)) 
                                                           if y is not sentinel]
['a', 'd', 'e', 'b', 'f', 'c', 'g', 'h']
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top