5
votes

J'ai besoin de fusionner des éléments de sous-liste en python

J'ai les listes de données suivantes

data1 = [[4,5,9],[4,7,2],[11,13,15]]
data2 = [[1,2,3,7],[3,6,8,5],[12,10,15,17]]
for i in range (0,2):
    for j in range(0,3):
        data1[i].extend(data2[j])
print(data1)

Je veux que la fusion de la liste se fasse comme suit.

data = [[4,5,9,1,2,3,7], [4,7,2,3,6,8,5], [11,13,15,12,10,15,17]]

i.e. fusionner les éléments à l'index 0 dans data1 et data2 et fusionner les éléments à l'index 1 dans data1 et data 2 et ainsi de suite ..

data1 = [[4,5,9],[4,7,2],[11,13,15]]
data2 = [[1,2,3,7],[3,6,8,5],[12,10,15,17]]


0 commentaires

5 Réponses :


4
votes

Utilisez zip () avec la compréhension de la liste:

data1 = [[4,5,9],[4,7,2],[11,13,15]]
data2 = [[1,2,3,7],[3,6,8,5],[12,10,15,17]]

for i in range(len(data1)):
    data1[i].extend(data2[i])

print(data1)
# [[4, 5, 9, 1, 2, 3, 7], [4, 7, 2, 3, 6, 8, 5], [11, 13, 15, 12, 10, 15, 17]]


Si vous en avez besoin de manière normale, vous pouvez vous débarrasser d'une boucle dans votre code (en supposant que les deux listes sont de longueur égale):

data1 = [[4,5,9],[4,7,2],[11,13,15]] 
data2 = [[1,2,3,7],[3,6,8,5],[12,10,15,17]]

data = [x+y for x, y in zip(data1, data2)]
# [[4, 5, 9, 1, 2, 3, 7], [4, 7, 2, 3, 6, 8, 5], [11, 13, 15, 12, 10, 15, 17]]


2 commentaires

les deux options semblent fonctionner correctement et sont rapides. Voir ma réponse avec des comparaisons de temps.


@Ralf, super. Merci d'avoir proposé des comparaisons de temps.



4
votes

Essayez ce qui suit:

merged = np.hstack(data_to_merge)

Vous pouvez également utiliser le hstack de numpy, que je trouve un peu plus intuitif

data_to_merge = [data1,data2]
merged = [sum(ds,[]) for ds in zip(*data_to_merge)]


6 commentaires

utiliser sum pour additionner 2 listes semble vraiment gonflé.


Utiliser sum est mieux que d'ajouter si l'OP a plus de deux variables data1 , data2 etc.


non car les performances en souffrent. sum a une complexité quadratique sur les listes.


Utilisez ensuite le hstack de numpy.


La documentation sur sum recommande d'utiliser itertools.chain pour concaténer les itérables. par exemple. liste (itertools.chain.from_iterable (zip (* data_to_merge)))


@Rob vos deux solutions fonctionnent avec plusieurs listes, mais sont considérablement plus lentes que les options de l'autre réponse (ne pas les discréditer, simplement que vous êtes tous conscients de la différence). Voir ma réponse avec comparaison de temps.



2
votes

J'ai comparé les solutions données dans d'autres réponses:

>>> import timeit
>>> timeit.timeit('f(data)', 'from __main__ import data,  f1 as f')
0.6496335420088144
>>> timeit.timeit('f(data)', 'from __main__ import data,  f2 as f')
1.1647848110005725
>>> timeit.timeit('f(data)', 'from __main__ import data,  f3 as f')
0.6762638779910048
>>> timeit.timeit('f(data)', 'from __main__ import data,  f4 as f')
8.561359490995528

Et les horaires sont:

def f1(original_data):
    return [
        x+y
        for x, y in zip(*original_data)]

def f2(original_data):
    return [
        sum(x, [])
        for x in zip(*original_data)]

def f3(original_data):
    data_1 = original_data[0]
    data_2 = original_data[1]

    for i in range(len(data_1)):
        data_1[i].extend(data_2[i])

    return data_1

def f4(original_data):
    return np.hstack(original_data).tolist()

La version dans mon f1 () semble être le plus rapide pour ces listes courtes.

Remarque: soyez prudent avec le code dans f3 () , car il modifie les données d'origine, vous devez donc l'exécuter comme le dernier; les autres fonctions renvoient une nouvelle copie et ne touchent pas l'original.

Une différence est que la version de f2 () fonctionne pour plusieurs listes, pas seulement 2; mais c'est plus lent. f4 () (en utilisant numpy ) fonctionne également pour plusieurs listes, mais c'est BEAUCOUP plus lent.


0 commentaires

3
votes

Si vous êtes sûr que data1 et data2 ont toujours le même nombre d'éléments (sous-listes), vous pouvez utiliser map de la manière suivante:

[[4, 5, 9, 1, 2, 3, 7], [4, 7, 2, 3, 6, 8, 5], [11, 13, 15, 12, 10, 15, 17]]

sortie:

data1 = [[4,5,9],[4,7,2],[11,13,15]]
data2 = [[1,2,3,7],[3,6,8,5],[12,10,15,17]]
data = list(map(lambda x,y:x+y,data1,data2))
print(data)


0 commentaires

1
votes

Vous pouvez utiliser l'opérateur concat () et la fonction starmap();:

from operator import concat
from itertools import starmap

list(starmap(concat, zip(data1, data2)))
# [[4, 5, 9, 1, 2, 3, 7], [4, 7, 2, 3, 6, 8, 5], [11, 13, 15, 12, 10, 15, 17]]


0 commentaires