5

I have a list that have different length in each dimension like below:

list1=[[2,3,4],[1],[77,8,27,12],[25,15]]

and I have another list with the same number of element like:

list2=[a,b,c,d,e,f,g,h,i,j]

I want to reshape my list2 as list1 and to process two lists together in a for loop.

user70
  • 597
  • 2
  • 7
  • 24
  • @abarnet, isn't OP asking the opposite? "*I want to reshape my list2 as list1*" – sacuL Aug 26 '18 at 19:45
  • @sacul Oops; you're right… Reopening. (In case I'm wrong, the canonical dup was [this one](https://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python).) – abarnert Aug 26 '18 at 19:46
  • Your `list2` is not a valid list, unless you already have a bunch of variables named `a` through `j` that you're not showing us. That makes it harder to copy and paste your example to show how to solve the problem, because without rewriting your example, any solution is just going to raise a `NameError`. – abarnert Aug 26 '18 at 19:55

3 Answers3

3

Flattening list1 to match list2 is easy—either just use itertools.chain.from_iterable(list)), or flat1 = [elem for sublist in list1 for elem in sublist], or the various other options in this question.

Going the other way is a bit more complicated. But, rather than looking for a one-liner, let's just do it explicitly: Create an iterator over list2, and pull elements off it as needed:

def zipstructured(list1, list2):
    iter2 = iter(list2)
    for sublist1 in list1:
        sublist2 = list(itertools.islice(iter2, len(sublist1)))
        yield sublist1, sublist2

Now you can just do this:

>>> list1=[[2,3,4],[1],[77,8,27,12],[25,15]]
>>> list2=['a','b','c','d','e','f','g','h','i','j']
>>> for sub1, sub2 in zipstructured(list1, list2):
...     print(sub1, sub2)
[2, 3, 4] ['a', 'b', 'c']
[1] ['d']
[77, 8, 27, 12] ['e', 'f', 'g', 'h']
[25, 15] ['i', 'j']
abarnert
  • 354,177
  • 51
  • 601
  • 671
3

Here's a kind of cute way.

list1 = [[2,3,4],[1],[77,8,27,12],[25,15]]
list2 = list("abcdefghij")

list2_iterator = iter(list2)
list2_reshaped = [[next(list2_iterator) for _ in sublist] for sublist in list1]

print(list2_reshaped)

Out: [['a', 'b', 'c'], ['d'], ['e', 'f', 'g', 'h'], ['i', 'j']]

I don't know if it's possible with pure comprehensions.

Denziloe
  • 7,473
  • 3
  • 24
  • 34
  • This answer assumes the OP will know how to solve the second half of his problem with `zip`, which I'm not sure we can assume. Also, I think `islice` might be clearer here than the inner comprehension. But still, nice showing how to do this separately from the `zip`, instead of entangled with it as in my answer. – abarnert Aug 26 '18 at 20:04
  • 1
    Yes I was assuming OP can do that and was just stating the motivation for reshaping the data. That might not be the case. But I'm not sure in what way they'd like to iterate over them together (there are a couple of sensible options), so I can't answer that without more info from the OP. – Denziloe Aug 26 '18 at 20:06
  • 2
    PS, you can _always_ do it with pure comprehensions, it just isn't always a good idea… To cram an assignment into an comprehension (without assignment expressions), just throw a 1-element loop in outside the other loops: `[[next(list2_iterator) for _ in sublist] for list2_iterator in [iter(list2)] for sublist in list1]`. Obviously nowhere near as readable as what you have now. – abarnert Aug 26 '18 at 20:07
  • I suspected something like that might be possible. Yes, I imagine that's almost never a good idea. Thanks for the insight. – Denziloe Aug 26 '18 at 20:09
1

If you want to process them in a loop, you can just do this:

list1=[[2,3,4],[1],[77,8,27,12],[25,15]]

list2=["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]

last = 0

for ele in list1:
    print(ele, list2[last : last + len(ele)])
    last += len(ele)

Result:

([2, 3, 4], ['a', 'b', 'c'])
([1], ['d'])
([77, 8, 27, 12], ['e', 'f', 'g', 'h'])
([25, 15], ['i', 'j'])
Akavall
  • 82,592
  • 51
  • 207
  • 251