Помогите использовать * args в функции соответствия кортежей Python - PullRequest
1 голос
/ 11 августа 2011

Я пытаюсь построить функцию в Python, которая выдает значения двух словарей, ЕСЛИ конкретное значение из dict1 соответствует конкретному значению dict2. Моя функция выглядит так:

def dict_matcher(dict1, dict2, item1_pos, item2_pos):
"""Uses a tuple value from dict1 to search for a matching tuple value in dict2. If a match is found, the other values from dict1 and dict2 are returned."""
for item1 in dict1:
    for item2 in dict2:
        if dict1[item1][item1_pos] == dict2[item2][item2_pos]:
            yield(dict1[item1][2], dict2[item2][6])

Я использую dict_matcher вот так:

matches = [myresults for myresults in dict_matcher(dict1, dict2 , 2, 6)]
print(matches)

Когда я печатаю matches, я получаю список правильно совпадающих значений dict1 и dict2, например:

[('frog', 'frog'), ('spider', 'spider'), ('cricket', 'cricket'), ('hampster', 'hampster')]

Как я могу добавить переменные аргументы к этой функции, чтобы, помимо печати соответствующих значений из каждого словаря, я также мог печатать другие значения каждого элемента словаря в случаях, когда dict1[item1][2] and dict2[item2][6] соответствует? Могу ли я использовать * args? Спасибо за помощь.

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

dict1 = {1: ('frog', 'green'), 2: ('spider', 'blue'), 3: ('cricket', 'red')}

dict2 = {a: ('frog', 12.34), b: ('ape', 22.33), c: ('lemur', 90.21)}

dict_matcher(dict1, dict2, 0, 0) найдет совпадающие значения для значения [0] из dict1 и значения [0] из dict2. В этом случае единственным совпадением является «лягушка». Моя функция выше делает это. То, что я пытаюсь сделать, это расширить функцию, чтобы иметь возможность распечатывать другие значения из элементов словаря, где dict1[value][0] == dict2[value][0] Я хочу, чтобы это было указано в аргументе функции.

Ответы [ 3 ]

1 голос
/ 11 августа 2011

Вы можете использовать объекты среза :

def dict_matcher(dict1, dict2, pos1, pos2, slicer1=(), slicer2=()):
    slice1 = slice(*slicer1) if slicer1 else slice(len(dict1))
    slice2 = slice(*slicer2) if slicer2 else slice(len(dict2))
    for data1 in dict1.values():
        for data2 in dict2.values():
            if data1[pos1] == data2[pos2]:
                yield data1[slice1], data2[slice2]

for result1, result2 in dict_matcher(my_dict, your_dict, 2, 6, (3, 8, 2), (2, 6)):
    print result1, result2
  • some_list[slice(3, 8, 2)] эквивалентно some_list[3:8:2], что дает вам каждый второй элемент some_list, начиная с четвертогоэлемент (который имеет индекс 3) до восьмого элемента.
  • some_list[slice(2, 6)] эквивалентен some_list[2:6], давая вам каждый элемент some_list, начиная с третьего элемента (который имеет индекс 2) дошестой элемент.
  • some_list[slice(7)] эквивалентен some_list[:7], что дает вам каждый элемент от some_list до седьмого элемента.

Если вы пропустите slicer1/2аргументы, функция предполагает, что вы хотите, чтобы весь список и срезы были установлены соответственно.

Также я удалил ненужные поиски в словаре.

0 голосов
/ 11 августа 2011

Вы хотите указать произвольное количество пар индексов для сравнения совпадений?

Как-то так?

def matcher(d1, d2, *args):
    indexes = zip(args[0::2], args[1::2])
    for a, b in indexes:
        for value1 in dict1.values():
            for value2 in dict2.values():
                x, y = value1[a], value2[b]
                    if x == y:
                        yield x, y

dict1 = {1: ('frog', 'green'), 2: ('spider', 'blue'), 3: ('cricket', 'red')}
dict2 = {a: ('frog', 12.34), b: ('ape', 22.33), c: ('lemur', 90.21)}

matches = list(matcher(d1, d2, 
                        0, 0, # first pair to search for matches
                        1, 1  # second pair, 
                        # ... and so on,
))

print matches
# [('frog', 'frog')]

Не думаю, что это ужасноможно использовать, но это сделало бы это.Это все равно будет работать, если вы укажете нечетное количество аргументов из-за магии нарезки.Тем не менее, из-за этого интерфейс вашей функции соответствия будет легко использовать неправильно.

Я бы настоятельно подумал о чем-то более похожем на:

def matcher(d1, d2, indexes_to_check):
    ...
print list(matcher(d1, d2, [(0, 0), (1, 1), ...]))

def matcher(d1, d2, *indexes_to_check):
    ...
print list(matcher(d1, d2, (0, 0), (1, 1)))
0 голосов
/ 11 августа 2011

Вы сказали, что называете его

matches = [myresults for myresults in dict_matcher(dict1, dict2 , 2, 6)]

Вы должны называть его

matches = list(dict_matcher(dict1, dict2 , 2, 6))

, а его подпись

def dict_matcher(dict1, dict2, item1_pos, item2_pos, *args):

Итак 4аргументы переданы, и 4 названы аргументы.Таким образом, *args приводит к args = None.

Я не уверен, что именно вы хотите, но если вы сделаете

yield dict1[item1][item1_pos], dict2[item2][item2_pos]

Вы получите то же самое, что и отделать

yield dict1[item1][2], dict2[item2][6]

Если вы хотите получить все соответствующие элементы, выполните

yield dict1[item1], dict2[item2]

Если вы хотите получить по одному элементу от каждого, но не от соответствующего элемента, выполните

def dict_matcher(dict1, dict2, item1_pos, item2_pos, other1_pos, other2_pos):

и

yield dict1[item1][other1_pos], dict2[item2][other2_pos]

и

matches = list(dict_matcher(dict1, dict2 , 2, 6, 3, 8)) 

или что угодно вместо 3 и 8.

Если вы хотите получить несколько, но не всепредметы, делайте

def dict_matcher(dict1, dict2, item1_pos, item2_pos, other1_poss, other2_poss):

и

yield [dict1[item1][i] for i in other1_poss], [dict2[item2][i] for i in other2_poss]

и

matches = list(dict_matcher(dict1, dict2 , 2, 6, (2, 3), (6, 8))) 

или что угодно вместо [2, 3] и [3, 8].

Если вы не это имели в виду, дайте мне знать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...