Как зациклить два списка списков одновременно и заменить значения из одного списка другим списком? - PullRequest
1 голос
/ 11 апреля 2019

У меня есть два списка списков (а и б)

Они оба имеют только 2 индекса в строке.

a (50000 строк) выглядит так:

|name|age|
|----|---|
|Dany|021|
|Alex|035|

Как список списков, выглядит так:

[['Dany', '021'],['Alex','035'], etc...]

b (2000 строк) выглядит так:

|name|age|
|----|---|
|Paul|   |
|Leon|   |

Как список списков, выглядит так:

[['Paul', ''],['Leon',''], etc...]

Вопрос: Я хочу перебирать a и b одновременно - для каждой итерации a, если a[0] находится в b[0], я хочу добавить соответствующий a[1] в b[1].

С точки зрения мирян, я хочу добавить возраст в мой список b, пройдя по моему списку a, проверив, есть ли имя в списке a и, если это так, взять соответствующий возраст и добавить его. в списке b для соответствующего имени.

Я пробовал вложенный цикл (итерация по b и для каждой итерации, итерация по a, чтобы проверить, существует ли какая-либо итерация a в a[0] в этой итерации b в b[0]), но просто продолжай теряться после этого.

for row in b[1:]: # Excluding the headers
    b_name = row[0]
    b_age = row[1]
    for row in a[1:]:
        if b_name in row[0]:
            b_age = row[1]
        else:
            b_age = ''

Проблема в том, что я получаю только одно значение для b_age, но должно быть 2000 уникальных b_age значений?

Ответы [ 6 ]

0 голосов
/ 11 апреля 2019

Я думаю, что многие другие упоминали; Использование здесь словарей значительно упростит жизнь, вы можете преобразовать их в словари, обработать данные и добавить возраст, а затем преобразовать обратно в списки, если это то, что вам нужно. Этот код делает именно это:

a = [['Dany', '021'], ['Alex','035'], ['Joe', '054']]
b = [['Alex',''], ['Dany', ''], ['Jane', '']]

print(a)
print(b)
print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')

# convert to dict for simplicity
a_dictionary  = dict(zip([e[0] for e in a], [e[1] for e in a]))
b_dictionary  = dict(zip([e[0] for e in b], [e[1] for e in b]))
a_intersect_b = list(set(a_dictionary.keys()) & set(b_dictionary.keys()))

print(a_dictionary)
print(b_dictionary)
print(a_intersect_b)
print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')

# copy ages to b
for k in a_intersect_b:
    b_dictionary[k] = a_dictionary[k]

print(a_dictionary)
print(b_dictionary)
print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')

# go back to lists
a = [[name, age] for name, age in zip(a_dictionary.keys(), a_dictionary.values())]
b = [[name, age] for name, age in zip(b_dictionary.keys(), b_dictionary.values())]

print(a)
print(b)
print('++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')

Выход:

[['Dany', '021'], ['Alex', '035'], ['Joe', '054']]
[['Alex', ''], ['Dany', ''], ['Jane', '']]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{'Dany': '021', 'Alex': '035', 'Joe': '054'}
{'Alex': '', 'Dany': '', 'Jane': ''}
['Alex', 'Dany']
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{'Dany': '021', 'Alex': '035', 'Joe': '054'}
{'Alex': '035', 'Dany': '021', 'Jane': ''}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[['Dany', '021'], ['Alex', '035'], ['Joe', '054']]
[['Alex', '035'], ['Dany', '021'], ['Jane', '']]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0 голосов
/ 11 апреля 2019

со списками вы можете:

a = [['Dany', '021'],['Alex','035'], ['Paul', '060'],['Leon','070']]
b = [['Paul', ''],['Leon','']]

for i, b_item in enumerate(b):
    for a_item in a:
        if b_item[0]==a_item[0]:
            b[i] = a_item
            break

print(b)

выход

[['Paul', '060'], ['Leon', '070']]
0 голосов
/ 11 апреля 2019

Если вы хотите обновить значения в b, вам нужно перебрать индекс строки b . Цикл значений не будет работать, так как они не сохраняют свою связь с исходной строкой / столбцом в b.

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

Попробуйте вместо этого:

for b_row_index in range(1, len(b)): # Excluding the headers
    b_name = b[b_row_index][0]
    for a_row in a[1:]:
        if b_name in a_row[0]:
            b[b_row_index][1] = a_row[1]
            break
    else:
        b[b_row_index][1] = ''
0 голосов
/ 11 апреля 2019

Вы можете попытаться преобразовать a в словарь, выполнив a_dict = dict(a), что приведет к чему-то вроде этого:

{'Dany': '021', 'Alex': '035', etc...}

Затем вы можете сделать что-то простое, как это:

for person in b:
    if person[0] in a_dict:
        person[1] = a_dict[person[0]]

Это должно дать вам что-то вроде этого в b:

[['Paul', ''], ['Leon', ''], ['Alex', '035'], etc...]
0 голосов
/ 11 апреля 2019

Вы захотите указать возраст, чтобы вы могли выполнить серию быстрых O (1) поисков для каждой строки в b. Я бы начал с чего-то вроде:

# Make a dictionary of names to their ages
age = dict(a)

for row in b:
    try:
        # Set the age of this row to the age of row[0]
        row[1] = age[row[0]]
    except KeyError:
        # End up here if row[0] is not in the "ages" dict
        pass
0 голосов
/ 11 апреля 2019

Предполагая, что имена в a уникальны, вы можете создать dict из a, чтобы избежать повторения его снова и снова, когда вы заменяете пустые строковые значения в b.Например (добавили пару элементов в ваши примеры, чтобы проиллюстрировать, что произойдет, если имя в b не существует в a):

a = [['Dany', '021'], ['Alex','035'], ['Joe', '054']]
b = [['Alex',''], ['Dany', ''], ['Jane', '']]

d = {k: v for k, v in a}
b = [[k, d[k]] if k in d else [k, v] for k, v in b]
print(b)
# [['Alex', '035'], ['Dany', '021'], ['Jane', '']]

Если список, с которым вы на самом деле работаете, простопростой список пар, как в примере, тогда вы могли бы заменить приведенное выше понимание dict на dict(a).

Также, если неясно, различные ссылки k, v предназначены для удобства распаковкивложенные пары, но вы можете просто использовать одну переменную и получить доступ с использованием значений индекса, таких как:

{x[0]: x[1] for x in a}
...