Получить уникальные продукты между списками и поддерживать порядок ввода - PullRequest
0 голосов
/ 04 мая 2018

Существует довольно много вопросов об уникальном (декартовом) произведении списков, но я ищу что-то особенное, чего не нашел ни в одном из других вопросов.

Мой ввод всегда будет состоять из двух списков. Когда списки идентичны, я хочу получить все комбинации, но когда они разные, мне нужен уникальный продукт (т.е. порядок не имеет значения). Однако , кроме того, мне также необходимо сохранить порядок, в том смысле, что порядок ввода имеет значение. На самом деле, мне нужно, чтобы элементы в первом списке всегда были первым элементом кортежа продукта.

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

import itertools

xs = ['w']
ys = ['a', 'b', 'c']

def get_up(x_in, y_in):
    if x_in == y_in:
        return itertools.combinations(x_in, 2)
    else:
        ups = []
        for x in x_in:
            for y in y_in:
              if x == y:
                  continue
              # sort so that cases such as (a,b) (b,a) get filtered by set later on
              ups.append(sorted((x, y)))
        ups = set(tuple(up) for up in ups)
        return ups

print(list(get_up(xs, ys)))
# [('c', 'w'), ('b', 'w'), ('a', 'w')]

Как видите, результатом является список уникальных кортежей, упорядоченных по алфавиту. Я использовал сортировку, чтобы отфильтровать дублирующиеся записи, используя набор. Но поскольку первый список (xs) содержит w, я хочу, чтобы кортежи имели этот w в качестве первого элемента.

[('w', 'c'), ('w', 'b'), ('w', 'a')]

Если есть совпадение между двумя списками, порядок элементов, присутствующих в обоих списках, не имеет значения., Поэтому для xs = ['w', 'a', 'b'] и ys = ['a', 'b', 'c'] порядок для a не имеет значения

[('w', 'c'), ('w', 'b'), ('w', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'c')]
                                         ^

или

[('w', 'c'), ('w', 'b'), ('w', 'a'), ('a', 'c'), ('b', 'a'), ('b', 'c')]
                                                     ^

Желательно, чтобы у меня был генератор (когда возвращается combinations). Меня также интересует только Python> = 3.6.

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

Соберите кортежи с сохранением порядка (например, когда списки идентичны), затем отфильтруйте, удалив кортежи, обратные к которым также есть в списке.

if x_in == y_in:
        return itertools.combinations(x_in, 2) 
    else:
        seen = set()
        for a,b in itertools.product(x_in, y_in):
            if a == b or (b, a) in seen:
                continue
            else:
                yield (a,b)
                seen.add((a,b))

Это даст вам кортежи в (x, y) порядке; когда происходят и (a,b), и (b,a), вы получаете только тот заказ, который был замечен первым.

0 голосов
/ 05 мая 2018

Я дам ответ на свой вопрос, хотя держу пари, что есть лучшее решение, использующее itertools или другие.

xs = ['c', 'b']
ys = ['a', 'b', 'c']


def get_unique_combinations(x_in, y_in):
    """ get unique combinations that maintain order, i.e. x is before y """
    yielded = set()
    for x in x_in:
        for y in y_in:
            if x == y or (x, y) in yielded or (y, x) in yielded:
                continue

            yield x, y
            yielded.add((x, y))

    return None

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