Как «соединить» частично скрытые номера по * (Python) - PullRequest
0 голосов
/ 05 апреля 2020

Я сделаю это максимально простым.

Допустим, у вас есть список кортежей, например:

[('0000************', 'b'), ('****1234********', 'a'),
('****1111****3333', 'b')]

Как мне соединить числа одного типа. В основном превратить приведенный выше пример во что-то вроде этого:

[('****1234********', 'a'), ('00001111****3333', 'b')]

Ответы [ 4 ]

3 голосов
/ 05 апреля 2020

Одно из возможных решений: создать словарь первых значений, проиндексированных вторым, и, когда будет найдено повторяющееся второе значение, объединить первые значения (в данном случае я дал приоритет первым). Затем преобразуйте этот словарь обратно в список кортежей:

tups = [('0000************', 'b'), ('****1234********', 'a'), ('****1111****3333', 'b')]

def merge_nums(n, m):
    return ''.join(a if a != '*' else b for a, b in zip(n, m))

out = {}
for (v, k) in tups:
    out[k] = merge_nums(out[k], v) if k in out else v
res = [(v, k) for k, v in out.items()]

print(res)

Вывод:

[('****1234********', 'a'), ('00001111****3333', 'b')]
0 голосов
/ 05 апреля 2020

Вы можете использовать itertools.groupby:

from itertools import groupby as gb
d = [('0000************', 'b'), ('****1234********', 'a'), ('****1111****3333', 'b')]
def merge(vals):
  return ['*' if not (x:=list(filter(str.isdigit, j))) else x[0] for j in zip(*vals)]

r = [(''.join(merge([j for j, _ in b])), a) for a, b in gb(sorted(d, key=lambda x:x[-1]), key=lambda x:x[-1])] 

Выход:

[('****1234********', 'a'), ('00001111****3333', 'b')]
0 голосов
/ 05 апреля 2020

Предполагая, что вам нужно будет сопоставлять только пары строк, одна из которых имеет ди git, а другая нет, вы можете l oop через все возможные пары кортежей, извлекать кортежи, когда они совпадают, затем объедините их строки. Я расширил ваш список примеров кортежей, чтобы показать, что код можно обобщать.

import itertools

list_of_tuples = [('0000************', 'b'), ('****1234********', 'a'),
('****1111****3333', 'b'), ('0000************', 'a')]

# combine two strings of the same length by digit
def combine_strings(str1, str2):
    new_string = ''
    for index, char in enumerate(str1):
        if char.isdigit():
            new_string += char
        else:
            new_string += str2[index]
    return new_string

# return all pairs of tuples that have a matching second element
def get_pairs(list_of_tuples):
    all_matches = []
    for pair in itertools.combinations(list_of_tuples, 2):
        if pair[0][1] == pair[1][1]:
            all_matches.append(pair)
    return all_matches

def combine_tuples(tuple1, tuple2):
    return (combine_strings(tuple1[0], tuple2[0]), tuple1[1])

all_matched_tuples = get_pairs(list_of_tuples) 
print(all_matched_tuples)
list_matched_tuples = []
for pair in all_matched_tuples:
    list_matched_tuples.append(combine_tuples(pair[0], pair[1]))

Вывод:

> list_matched_tuples
[('00001111****3333', 'b'), ('00001234********', 'a')]
0 голосов
/ 05 апреля 2020

Не уверен, насколько это эффективно, но это работает. Обратите внимание, что вы можете перезаписывать числа, если для каждого типа есть значения с одинаковым индексом.

x = [('0000************', 'b'), ('****1234********', 'a'), ('****1111****3333', 'b')]

types = {}

for y in x:
    if y[1] in types:
        i = 0
        for z in y[0]:
            if z != '*':
                types[y[1]] = types[y[1]][0:i] + z + types[y[1]][i:-1]
            i += 1
    else:
        types[y[1]] = y[0]

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