Понимание списка из двух списков различной длины ([2 * n] и [2 * m]) в один единственный список [3 * len (уникальный (n [0], m [0]))] - PullRequest
0 голосов
/ 05 февраля 2019

Данные списки:

a = [
 [2, 10  ],
 [3, 120],
 [4, 30 ]
]

b = [
 [1, 10 ],
 [2, 40]
]

Как я могу использовать списки, архивирование, мин / макс, объединение, перечисление, izip_longest, map и / или лямбду, чтобы вернуть третий список, который упорядоченлевая переменная, с дубликатами левой переменной, объединенными в одну строку, сохраняя положение исходных списков в средней и последней позициях.Предположим, что a всегда будет в средней позиции, а b всегда будет в последней позиции, так как a и b могут иметь различную длину.

c = [
 [1, None, 10   ],
 [2, 10  , 40   ],
 [3, 120 , None ],
 [4, 30  , None ]
]

Для копирования одной строки/ Pasting

a = [[2, 0],[3, 120],[4, 30]]
b = [[1, 0],[2, 40]]
c = [[1, None, 0],[2, 0, 40],[3, 120 , None],[4, 30, None]]

Спасибо за помощь.Я заблудился, пытаясь найти желанного однострочника, чтобы помочь мне понять образ мышления гуру питона!

Ответы [ 4 ]

0 голосов
/ 06 февраля 2019

Для этого вы можете использовать панд:

import pandas as pd
A = pd.DataFrame(dict(a),index=[0]).T
B = pd.DataFrame(dict(b),index=[0]).T
C = A.join(B,how='outer',lsuffix='l').reset_index().values
C
array([[  1.,  nan,  10.],
       [  2.,  10.,  40.],
       [  3., 120.,  nan],
       [  4.,  30.,  nan]])

Если этого недостаточно, и вы хотите None вместо nan, тогда вы можете сделать:

pd.np.where(pd.np.isnan(C),None,C).tolist()
[[1.0, None, 10.0], [2.0, 10.0, 40.0], [3.0, 120.0, None], [4.0, 30.0, None]]
0 голосов
/ 05 февраля 2019

Использование схемы цепочки + понимание списка:

>>> from collections import ChainMap
>>> c = ChainMap(dict(a), dict(b))
>>> [[k] + [d.get(k) for d in c.maps] for k in c]
[[1, None, 0], [2, 0, 40], [3, 120, None], [4, 30, None]]

Это легко обобщит использование более 2 списков ввода таким образом.

0 голосов
/ 05 февраля 2019

Подход 1 - преобразовать в диктанты и выполнить их слияние

a = [[2, 0],[3, 120],[4, 30]]
b = [[1, 0],[2, 40]]

a_dict = dict(a)
b_dict = dict(b)
merged = [
    (key, a_dict.get(key), b_dict.get(key))
    for key in sorted(a_dict.keys() | b_dict.keys())]

Подход 2 - объединить отсортированные списки

Этот алгоритм должен бытьбыстрее, но работает, только если оба списка отсортированы по значению ключа.

a = [[2, 0],[3, 120],[4, 30]]
b = [[1, 0],[2, 40]]

merged = []
a_pos, b_pos = 0, 0
while a_pos < len(a) and b_pos < len(b):
    assert a_pos == 0 or a[a_pos][0] >= a[a_pos-1][0]
    assert b_pos == 0 or b[b_pos][0] >= b[b_pos-1][0]
    if a[a_pos][0] == b[b_pos][0]:
        merged.append((a[a_pos][0], a[a_pos][1], b[b_pos][1]))
        a_pos += 1
        b_pos += 1
    elif a[a_pos][0] < b[b_pos][0]:
        merged.append((a[a_pos][0], a[a_pos][1], None))
        a_pos += 1
    else:
        merged.append((b[b_pos][0], None, b[b_pos][1]))
        b_pos += 1

while a_pos < len(a):
    merged.append((a[a_pos][0], a[a_pos][1], None))
    a_pos += 1

while b_pos < len(b):
    merged.append((b[b_pos][0], None, b[b_pos][1]))
    b_pos += 1

print(merged)
0 голосов
/ 05 февраля 2019

Если вы не возражаете против создания одноразовых диктовок, что-то вроде:

da = dict(a)
db = dict(b)

cc = [[k, da.get(k), db.get(k)] for k in sorted(set(da) | set(db))]

, кажется, работает (по крайней мере, для вашего примера).

  • Эти диктовки позволяют вам«найти» строки по первому элементу
  • sorted(set(da) | set(db)) принимает отсортированное пересечение ключей двух словарей da и db.
  • Используя dict.getмы можем обработать случай, когда строка не существует изящно.(dict.get по умолчанию имеет значение None, поэтому нам не нужно его предоставлять, но вы можете, если хотите).
...