2016-09-08 2 views
0

Мне нужно решить эту проблему оптимизации с помощью Python. У меня есть список списков, каждый из которых содержит элементы. Например:Получите ограниченный список уникальных элементов из списка списков

l = [ 
     ['elem1'], 
     ['elem2'], 
     ['elem3','elem4'], 
     ['elem4','elem5'] 
    ] 

Что мне нужно, чтобы получить список r, что:

1) Оба списка должны иметь одинаковую длину

>>> len(r)==len(l) 
True 

2) Каждый выбранный элемент должен соответствовать к элементам того же индексного списка

>>> correct=True 
>>> for r_element in r: 
...  if r_element not in l[r.index(r_element)]: 
...   correct=False 
...   break 
...   
>>> correct 
True 

3) Элементы должны быть u Nique

>>> len(r) > len(set(r)) 
False 

Возможный результат здесь будет, например:

r = ['elem1','elem2','elem3','elem4'] 

Есть ли лучший способ сделать это? Или, может быть, не использовать списки, а некоторые другие структуры данных или некоторые конкретные пакеты Python?

Благодаря

+0

У вас есть код до сих пор? – grael

+0

Если элементы в 'r' уникальны, то 3) должны быть' False', но в любом случае. Просто сгладьте 'l' и удалите повторяющиеся элементы –

+0

@ Ev.Kounis True, спасибо – adefabritiis

ответ

0

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

l = [ 
     ['elem1', 'elem5'], 
     ['elem2'], 
     ['elem3','elem4'], 
     ['elem1','elem2'] 
    ] 

def constrained_list(l): 
    r = []    # final list 
    used = set()   # values used 
    if recurse(r, used, l): return r  # if successul in finding contrained list, return it 
    return "No valid list" 

def recurse(r, used, l): 
    if not l: return True  # base case, l has been completely processed 
    line = l[0]     # look at first line in l 
    for word in line: 
     if word not in used: 
      used.add(word)  
      r.append(word)  # try adding this word 
      if recurse(r, used, l[1:]): return True  # recurse on the rest of l, from 1 to end 
      used.remove(word) # if this choice didnt work, backtrack. 
      r.pop() 
    return False     

Это выводит:

['elem5', 'elem2', 'elem3', 'elem1'] 
+0

замените последний список в 'l' на' ['elem1', 'elem2'] 'и запустите его снова. Являются ли критерии № 2 не нарушенными? Это то, что я имел в виду в комментарии выше –

+0

@ Ev.Kounis. В этом случае нет способа удовлетворить это право? Ошибка утверждения будет поднята. Фактическая ошибка, которая может произойти, состоит в том, что первый элемент в 'l' является' ['elem1', 'elem5'] ', а затем последним элементом является' ['elem1', 'elem2'] '. В этом случае первый выбор будет испорчен, мы должны были бы выбрать «elem5», чтобы быть в первой позиции, а «elem1» - последним. – gowrath

+0

@ Ev.Kounis Я собираюсь удалить это; решение будет включать какой-то рекурсивный обратный отсчет, и я cba, чтобы написать его. – gowrath

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