2013-12-20 4 views
-1

Я хочу сделать следующее:Как сопоставить ключевые значения с помощью списков?

1] сравнить каждый элемент в списке a с b и сопоставить аналогичные значения.

a=[1, 2, 3, 6, 4, 5, 7, 8, 9] 
b=[4, 4, 5, 5, 7, 7, 9, 9, 10] 

Я попробовал следующее:

c = set(a) & set(b) 
>>> set([9,4,5,7]) 

2] Я хочу, чтобы эти преобразованные значения в том порядке, нумерации, как появляются в списке Ь, такие как 4,5,7,9.

3] и, наконец, я хочу использовать эти ключевые значения (4,5,7,9) и генерировать соответствующие значения из списка А, например:

4 (1,2) 
5 (3,6) 
7 (4,5) 
9 (7,8) 

Любые предложения будут высоко оценивает?

+0

Мне также хотелось бы получить отзывы о том, почему отрицательное голосование должно улучшить мои вопросы в будущем. – Ibe

+1

Лучшее название может помочь. «Как сравнивать списки» является очень широким и неопределенным. 'a == b' - там, я сравнил два списка;) – Iguananaut

+1

Я думаю, что люди реагируют на то, что вы не показывали никакого кода ... кроме того, что вы показали свое решение в части 1, это просто так тривиально, что это только одна строка, и люди, возможно, этого не заметили. Во всяком случае, правильна ли моя догадка или нет, это помогло бы, если бы вы дали некоторое представление о том, какие у вас были мысли, какой код вы пробовали и т. Д. Для двух других частей. – abarnert

ответ

2

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

a = [1, 2, 3, 6, 4, 5, 7, 8, 9] 
b = [4, 4, 5, 5, 7, 7, 9, 9, 10] 

r = dict([(x, []) for x in b]) 

for k, v in zip(b, a): 
    r[k] += [v,] 

Вот как для использования результатов:

>>> for k, v in r.items(): 
...  print k, v 
... 
9 [7, 8] 
10 [9,] 
4 [1, 2] 
5 [3, 6] 
7 [4, 5] 
>>> 
>>> print r[4] 
[1, 2] 

Это оптимизированная версия, которая будет работать быстрее с меньшими затратами использование памяти:

from itertools import izip 
from collections import defaultdict 
r = defaultdict(list) 

for k, v in izip(b, a): 
    r[k] += [v] 
+0

Спасибо. Он работает, как мне нужно. Только одна тривиальная вещь, использование следующего дает синтаксическую ошибку: 'r = dict ([k, tuple() для k в b])' – Ibe

+0

Я обновил ответ. Первая версия проста без импорта, а затем оптимизированная версия ниже. –

+1

Использование 'defaultdict (list)' с помощью 'append' или' + = [v] 'является концептуально более чистым и более эффективным. Но в противном случае отображение непосредственно между двумя списками с помощью 'zip' вместо сопоставления от одного к индексу (как мой ответ) является хорошим упрощением. Он может быть менее гибким, но он делает именно то, что хочет, в более очевидном коде, поэтому, если ему не нужна гибкость, зачем платить за него? – abarnert

2

Для решения проблемы 3, вам необходимо сравнить каждый лист против противоположного набора. И это решит ваш # 2 автоматически.

Есть и другие способы решения # 2, как с помощью OrderedSet (например, recipe, связанный с collections docs), но так как они не решат № 3, в этом нет смысла.


Если a значения очень велики, вы можете создать индекс структуру-а Dict, который отображает значение коллекции индексов-чтобы сделать это быстрее. Как это:

rev_a = collections.defaultdict(list) 
for index, value in enumerate(a): 
    rev_a[value].append(index) 

И тогда поиск часть становится еще проще и быстрее:

for b_value in b: 
    a_indices = rev_a[b_value] 
    if a_indices: 
     a_str = ','.join(map(str, a_indices)) 
     print('{} is associated with ({})'.format(b_value, a_str)) 

Или, если вы хотите создать какую-то структуру вместо печати на лету:

results = [(b_value, rev_a[b_value]) for b_value in b] 
results = OrderedDict((b_value, rev_a[b_value]) for b_value in b) 
# etc. 

это на самом деле не производят вывод, который вы просили, но ... Я не уверен, что выход которой вы просили су который должен был появиться. Если вы не берете соответствующие индексы из другого списка, а затем просматриваете их в первом списке? Это ... странно, если не сказать больше. Во всяком случае, структура индекса, подобная этой, должна сделать тривиальным выполнение любого правила, которое вы придумали, даже гораздо более странного, если вы можете это объяснить.

Например, замените a_str линию с этим:

a_str = ','.join(str(a[a_index] for index in a_indices)) 

... и Вы получите желаемый результат.

+1

error: 'AttributeError: объект 'list' не имеет атрибутов 'items'' ' AttributeError: объект' list 'не имеет атрибута' iteritems'' – Ibe

+0

@Ibe: Извините, это осталось от исходной версии. См. Редактирование. И +1 за улов! – abarnert

0

Вы можете использовать list comprehension

>>> a=[1, 2, 3, 6, 4, 5, 7, 8, 9] 
>>> b=[4, 4, 5, 5, 7, 7, 9, 9, 10] 
>>> [x for x in a if x in b] 
[4, 5, 7, 9] 
+0

Это решает часть, которую он уже знает, как решить (часть 1), менее эффективно, чем его существующее решение, и не разрешает часть 3 вообще. – abarnert

+1

Его существующее решение не решает проблему. Это не должно быть эффективным. Если вас беспокоит эффективность, вы будете использовать 'OrderedDict'. Попробуйте запустить код через 'timeit' когда-нибудь. –

+0

'set (a) & set (b)' решает часть своей проблемы, но не всю его проблему. Ваш ответ также решает часть его проблемы, но не всю его проблему, и она менее очевидна и медленнее для загрузки, и вы не даете никаких указаний или объяснений, почему вы думаете, что это лучше. И я понятия не имею, что подразумевают второе и третье предложения вашего комментария, тем более что я _did_ использовал 'OrderedDict' в своем ответе ... – abarnert

Смежные вопросы