0
def intercala_listas(lista1, lista2):

    l1 = ["b", "d", "f", "h"]
    l2 = ["a", "c", "e", "g"]
    assert intercala_listas(l1,l2) == ['a', 'b', 'c', 'd', 'e','f', 'g', 'h']
    assert l1 == ["b", "d", "f", "h"]
    assert l2 == ["a", "c", "e", "g"]

I have to make a function called intercala_lista which will receive two lists and return a third list which need to put the elements of the first list (l1) in the odd index and the elements of the second list (l2) at the even index, like the asserts shown.

I dodn't expect a complete answer, but I need an idea of how do that.


I tried something like this:

def intercala_listas(lista1, lista2):
    lista = [8]
    for i in range(len(lista)):
        if lista[i].index%2 == 0:
            lista[i] = lista1[i]
        else:
            lista[i] = lista2[i]
        return lista

I know I'm not using index properly in this function. Is the idea ok?

Marioanzas
  • 1,663
  • 2
  • 10
  • 33
  • 1
    `lista = [8]` creates a single-element list with one value, the number `8`, not an 8-element list. – abarnert Oct 17 '13 at 19:42
  • "Intercalate" is a strange word to use for this, which may have made it more difficult to search for an existing solution. – Karl Knechtel Sep 06 '22 at 01:17

8 Answers8

4

Hint: use the zip function:

>>> zip(l2, l1)
[('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', 'h')]

Regarding your answer: Python lists aren't arrays. They don't have a fixed size, so just append elements to the end:

def intercala_listas(lista1,lista2):
    # Assumes lista1 and lista2 are the same length 
    lista = []

    for i in range(len(lista1)):
        lista.append(lista1[i])
        lista.append(lista2[i])

    return lista

>>> print intercala_listas(list("aceg"), list("bdfh"))
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
David Cain
  • 16,484
  • 14
  • 65
  • 75
Blender
  • 289,723
  • 53
  • 439
  • 496
  • 1
    Nice explanation of what the OP was doing wrong/how close he was/how to fix it. – abarnert Oct 17 '13 at 19:43
  • 1
    … except that you need `len(lista) + len(listb)` (or `2 * len(lista)` or something similar), and then you need `lista1[i/2]`. Or, alternatively, you need to scrap the `if` and just do both each time. – abarnert Oct 17 '13 at 19:44
  • ty for your explanation, make this easy to understand now. –  Oct 17 '13 at 19:59
  • @abarnert: Guess that mental interpreter isn't running today. Thanks. – Blender Oct 17 '13 at 20:00
2

Here's a funky solution using Python's slice assignment with offset and step size, to show off some of Python's lesser known features - a nested list comprehension or other solutions using zip would probably be preferable in general. This solution assumes both lists have the same length:

def intersect_lists(l1, l2):
    result = [0] * len(l1) * 2 #create result list of required size
    result[::2] = l2 #assign l2 to the slice of every second item in result
    result[1::2] = l1 #as above but starting at offset 1
    return result
l4mpi
  • 5,103
  • 3
  • 34
  • 54
2

The zip function is designed to zip lists together. You seem to want to put the second one first, but you can do that by just reversing the arguments.

Meanwhile, this gives you a sequence of 2-tuples that you have to flatten. The right way to do this is to use chain. (Using sum is not only misleading, it's also quadratically slow.)

Finally, the end result of this will be some kind of iterable (in fact, an iterator), not a list, so you have to construct a list out of it. So:

def intercala_listas(a, b):
    return list(itertools.chain.from_iterable(zip(b, a)))
abarnert
  • 354,177
  • 51
  • 601
  • 671
2
import itertools

list(itertools.chain(*zip(l2, l1)))
# ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']

or

list(itertools.chain.from_iterable(zip(l2, l1)))
# ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
pylang
  • 40,867
  • 14
  • 129
  • 121
1

Using sum() for this problem in particular can be confusing and slow (see comments), and that's why it'd be a better idea to avoid it. Here's how:

[e for ts in zip(l2, l1) for e in ts]
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Óscar López
  • 232,561
  • 37
  • 312
  • 386
1

Short and sweet:

list(sum(zip(l2, l1), ()))
nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • 1
    Using sum on tuples is a bad idea. Besides being questionably readable (at least the creator of the sum method thinks it's misleading and unreadable), it's also quadratically slow. With lists, at least you _can_ work around that (e.g., by using `functools.reduce` and `operator.iadd`); with tuples, there's really nothing you can do. – abarnert Oct 17 '13 at 19:42
0

You could zip the lists, and then flatten the result in a comprehension:

def intercala_listas(a, b):
    c = list(zip(a, b))
    return [elt for sublist in c for elt in sublist]
dckrooney
  • 3,041
  • 3
  • 22
  • 28
0
def intercalate_2lists(l1, l2, s1=0, s2=1, app=nan, incr=1, if_print= False):
    """
    Usage:  Intercalate two lists: L1 and L2 into a new list L3
    
        S1 and S2 are indices in L3 where interacalation of L1 or L2 will start.
        INCR is the number of empty elements APP added to L3 at each iteration,
        such iteration can be empty if current L3 index is inferior to min(S1, S2).
        Intercalation in L3 starts at min(S1,S2) and the first element of the corresponding list is used.
        Intercalation of the list corresponding to max(S1, S2) starts once the iteration through L3 reach the index max(S1, S2)
        if S1>0 and S2>0: L3 is appended with APP. until iteration of L3 reach min(S1, S2)
        if S1 == S2: S2 is incremented by 1 (user should avoid this situation)
        S1, S2 can be used to swap the order of integration of L1 and L2, i.e. id S2<S1: L2 will be used first
    Parameters:
    L1,L2   (list)(list) lists to intercalate
    S1,S2   (int),(int) indices in L3 to start to intercalate L1 and L2
    INCR    (int) step of increment of L3 (spacing between L1&L2 elements)
    APP     (var) element to put in empty cells of L3
    IF_PRINT (bool) Track assembly of L3. Use only for short L3 lists otherwise be ready to saturate your screen with printed output
    
    Return:
    L3 list
    """
    
    len_l1 = len(l1)
    len_l2 = len(l2)
    result = list()
    t1,t2 = False, False
    d1,d2 = False, False
    f1,f2 = True, True
    if s1 == s2: s2 += 1 # SAFEGUARD
    if incr == 0: incr=1 # SAFEGUARD
    c, c1, c2 = 0, 0 ,0
    while c1 < len_l1 or c2 < len_l2:
        for x in range(incr):
            result.append(app)
        if all([c >= s1, f1]): t1 = True; d1 = True; f1 = False; d2=False
        elif all([c >= s2, f2]): t2 = True; d2 = True; f2 = False; d1=False
        if if_print: print("beg:" + str(c) + '\t' + str(c1) + '\t' + str(c2), d1, d2)
        if t1:
            if d1:
                result[-1] = l1[c1]
                c1 += 1
                if t2:
                    if c2 < len_l2: d1 = False; d2 = True
                    if if_print: print("end:" + str(c) + '\t' + str(c1) + '\t' + str(c2), d1, d2)
                    if c1 == len_l1: t1 = False
                    c += incr
                    if if_print: print(result,'___')
                    continue
        if t2:
            if d2:
                result[-1] = l2[c2]
                c2 += 1
                if t1:
                    if c1 < len_l1: d1=True; d2 = False
        if if_print: print("end:" + str(c) + '\t' + str(c1) + '\t' + str(c2), d1, d2)
        if c1 >= len_l1: t1 = False
        if c2 >= len_l2: t2 = False
        c += incr
        if if_print: print(result)
    return result

Application of intercalate_2lists():

a = ["A", "B", "C", "D", "E", "F", "G"]
b = [1, 2, 3, 4]
# Use the default behavior
print("case1:", intercalate_2lists(a[:4], b))
print("case2:", intercalate_2lists(a, b))
print("case3:", intercalate_2lists(b, a))
# Use advanced modes
print("case4:", intercalate_2lists(a, b, s1=4, s2=2))
print("case5:", intercalate_2lists(b, a, s1=3, s2=10, incr=3, if_print=0))
print("case6:", intercalate_2lists(a[:4], b, s1=2, incr=1, if_print=0))

Results of the above calls:

case1:['A', 1, 'B', 2, 'C', 3, 'D', 4]
case2:['A', 1, 'B', 2, 'C', 3, 'D', 4, 'E', 'F', 'G']
case3:[1, 'A', 2, 'B', 3, 'C', 4, 'D', 'E', 'F', 'G']
case4:[nan, nan, 1, 2, 'A', 3, 'B', 4, 'C', 'D', 'E', 'F', 'G']
case5:[nan, nan, nan, nan, nan, 1, nan, nan, 2, nan, nan, 3, nan, nan, 'A', nan, nan, 4, nan, nan, 'B', nan, nan, 'C', nan, nan, 'D', nan, nan, 'E', nan, nan, 'F', nan, nan, 'G']
case6:[nan, 1, 'A', 2, 'B', 3, 'C', 4, 'D']

Since most answers in this post handle only lists of equal sizes, here is an artistic method capable of handling lists of different sizes.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
zlATOM
  • 1
  • 1