Как перебрать сразу два списка списков и заменить значения из одного списка другим списком?

#python #list #loops #iteration #nested-loops

#python #Список #циклы #итерация #вложенные циклы

Вопрос:

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

У них обоих всего 2 индекса на строку.

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

 |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] это in b[0] , я хочу добавить соответствующий a[1] into b[1] .

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

Я пробовал вложенный цикл (повторяя через b и для каждой итерации, a повторяя, чтобы проверить, существует ли какая-либо итерация a at a[0] в этой итерации b at 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 значений?

Комментарии:

1. Это должны быть словари, а не списки списков. Или вы должны использовать pandas .

2. Установка b_age значения не влияет на столбец списка, из которого оно получено.

3. Вы ничего не добавляете, вы просто заменяете переменную. Вы имеете в виду, что хотите добавить их в виде чисел, объединить строки или составить список всех значений?

4. @Barmar как я должен использовать pandas в этом случае?

5. IMO, pandas — это огромный перебор для такого маленького проекта и с такими простыми требованиями.

Ответ №1:

Предполагая, что имена в 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}
  

Комментарии:

1. Спасибо @benvc итак, если это не простой список пар, как мне это сделать?

2. @luca-martial — в зависимости от того, насколько сложны ваши вложенные списки, вы можете использовать модифицированную версию понимания dict в этом ответе. Если вложенные списки довольно сложные, было бы полезно, если бы вы опубликовали пример того, как они выглядят, чтобы мы могли лучше помочь.

Ответ №2:

Вы можете попытаться создать 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...]
  

Ответ №3:

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

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

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

 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] = ''
  

Ответ №4:

Вы захотите указать возраст, чтобы вы могли выполнить серию быстрых поисков 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
  

Комментарии:

1. В какой части? Здесь все работает так, как ожидалось.

Ответ №5:

с помощью списков вы можете:

 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']]
  

Ответ №6:

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

 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()) amp; 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', '']]