0

Edited for the sake of simplicity, as I have pin pointed the issue to 'argument unpacking'.
I am trying to write a function that interleaves an arbitrary number of lists as parameters. All the lists have equal length. The function should return one list containing all the elements from the input lists interleaved.

def interleave(*args):

    for i, j, k in zip(*args):
        print(f"On {i} it was {j} and the temperature was {k} degrees celsius.")

interleave(["Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split()],["rainy rainy sunny cloudy rainy sunny sunny".split()],[10,12,12,9,9,11,11])

Output:

On ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] it was ['rainy', 'rainy', 'sunny', 'cloudy', 'rainy', 'sunny', 'sunny'] and the temperature was 10 degrees celsius.

desired output:

On Monday it was rainy and the temperature was 10 degrees celsius.
On Tuesday it was rainy and the temperature was 12 degrees celsius.
On Wednesday it was sunny and the temperature was 12 degrees celsius.
On Thursday it was cloudy and the temperature was 9 degrees celsius.
On Friday it was rainy and the temperature was 9 degrees celsius.
On Saturday it was sunny and the temperature was 11 degrees celsius.
On Sunday it was sunny and the temperature was 11 degrees celsius.
Saurus
  • 79
  • 1
  • 7

2 Answers2

1

The recipe section of the itertools documentation calls this roundrobin:

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

For (equal-sized) lists specifically, you can simplify this to

def interleave(*args):
    return list(chain.from_iterable(zip(*args)))
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Seems abit advanced for the 1 week of python. The functions reminds of interfaces from java. – Saurus Jan 18 '20 at 15:02
  • @Saurus _The functions reminds of interfaces from java._ Which functions, and how? – AMC Jan 18 '20 at 15:39
  • The iterable interface in java also has a next(). The above example also utilized the iterator. – Saurus Jan 18 '20 at 16:06
  • @Saurus Well, yes. It makes use of the iterator protocol. `iterables` isn't restricted to lists; you could pass a mix of lists, tuples, sets, strings, dicts, or anything else that implements the iterator protocol. – chepner Jan 18 '20 at 16:53
1

Don't wrap the result of split in a list. So, change

interleave(["Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split()],["rainy rainy sunny cloudy rainy sunny sunny".split()],[10,12,12,9,9,11,11])

to

interleave("Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(),"rainy rainy sunny cloudy rainy sunny sunny".split(),[10,12,12,9,9,11,11]).

While the former will result in two lists of length 1 and a list of length 7 as arguments to interleave, the latter/change will result in three lists of length 7 as arguments. The latter is what you need for the zip operator to work as you desire.