2016-06-05 7 views
1

-первых, это то, что у меня есть на код до сих пор, я дам объяснение в немного:Присоединяйтесь списки с повторяющимися значениями

ll1 = [ 
'A', 
'B', 
'C', 
'D' 
] 

l2 = [ 
['A', 10], 
['B', 20], 
['D', 5], 
['A', 15], 
['B', 30], 
['C', 10], 
['D', 15] 
] 

dc = dict(l2) 
l3 = [[k, dc.get(k, 0)] for k in l1] 

Результат таков:

['A', 15] 
['B', 30] 
['C', 10] 
['D', 15] 

Первый список l1 выполнен из фиксированного количества ключей, а второй список l2 имеет значения для каждого ключа, указанного в первом списке. l2 вот только один пример, так как я получу значения позже (и эти значения будут указаны как список), но они будут иметь те же ключи, что и l1. Каждый ключ должен быть показан, ключ может быть повторен, но некоторые ключи могут иметь нулевое значение (например, элемент C).

Но когда список становится dict, первое значение каждой клавиши выбрасывается, возвращая уникальные ключи для словаря.

Как это сделать, чтобы результат был подобен приведенному ниже?

['A', 10] 
['B', 20] 
['C', 0] 
['D', 5] 
['A', 15] 
['B', 30] 
['C', 10] 
['D', 15] 

Другой пример:

database_keys = [ 
'First Name', 
'Last Name', 
'Email', 
'City' 
] 
database_input = [ 
['First Name', 'John'], 
['Last Name', 'Doe'], 
['Email', '[email protected]'], 
['First Name', 'Jane'], 
['Email', '[email protected]'] 
] 

Output: 
['First Name', 'John'] 
['Last Name', 'Doe'] 
['Email', '[email protected]'] 
['City', None] 
['First Name', 'Jane'] 
['Last Name', None] 
['Email', '[email protected]'] 
['City', None] 
+0

Этот ожидаемый результат выглядит так же, как 'l2', который у вас уже есть !? – schwobaseggl

+0

Да, я забыл упомянуть, что значения не предопределены, они будут иметь только те же ключи. Я отредактирую вопрос. –

+0

Там вы идете, модифицировали и дали еще один пример. @schwobaseggl –

ответ

3

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

import itertools 
def fill_the_blanks(data, keys): 
    keys = itertools.cycle(keys) 
    for name, value in data: 
     k = next(keys) 
     while name!=k: 
      yield [k,None] 
      k = next(keys) 
     yield [name,value] 


>>> from pprint import pprint 
>>> pprint(list(fill_the_blanks(l2, ll1))) 
[['A', 10], 
['B', 20], 
['C', None], 
['D', 5], 
['A', 15], 
['B', 30], 
['C', 10], 
['D', 15]] 
>>> pprint(list(fill_the_blanks(database_input,database_keys))) 
[['First Name', 'John'], 
['Last Name', 'Doe'], 
['Email', '[email protected]'], 
['City', None], 
['First Name', 'Jane'], 
['Last Name', None], 
['Email', '[email protected]']] 

в качестве альтернативы, если вы знаете, что первый ключ 'First Name' всегда будет означать начало записи, почему не просто использовать dict.fromkeys затем заполнить, пока вы не достигнете следующего «первого значения»:

def gen_dicts(data, keys): 
    first_key = keys[0] 
    entry = None #placeholder for first time 
    for name, value in data: 
     if name == first_key: 
      if entry is not None: #skip first time 
       yield entry 
      entry = dict.fromkeys(keys) 
     entry[name] = value 
    yield entry #last one 

>>> from pprint import pprint 
>>> pprint(list(gen_dicts(l2, ll1))) 
[{'A': 10, 'B': 20, 'C': None, 'D': 5}, {'A': 15, 'B': 30, 'C': 10, 'D': 15}] 
>>> pprint(list(gen_dicts(database_input, database_keys))) 
[{'City': None, 
    'Email': '[email protected]', 
    'First Name': 'John', 
    'Last Name': 'Doe'}, 
{'City': None, 
    'Email': '[email protected]', 
    'First Name': 'Jane', 
    'Last Name': None}] 
+0

Он отлично работал, большое спасибо. Я буду копать в dict.fromkeys и dict.cycle, это должно мне очень помочь. Еще раз спасибо. –

+0

'help (dict.fromkeys)' действительно идет вперед, но ищет [итераторы] (http://stackoverflow.com/questions/9884132/what-exactly-are-pythons-iterator-iterable-and-iteration-protocols) поможет вам больше, прежде чем смотреть в 'itertools.cycle', как только вы поймете на итерации' cycle', просто повторяйте повторение итерации снова и снова. –

1

Вот грязного путь:

l1 = [ 
'A', 
'B', 
'C', 
'D', 
] 

l2 = [ 
['A', 10], 
['B', 20], 
['D', 5], 

['A', 15], 
['B', 30], 
['C', 10], 
['D', 15], 

['A', 8], 
] 

# Assuming elements in l2 are ordered, try to make groups 
# of the same length of l1. 
l_aux = l1[:] 
l3 = [[]] 
for x in l2: 
    if x[0] in l_aux: 
     l3[-1].append(x) 
     l_aux.remove(x[0]) 
     continue 
    for y in l_aux: 
     l3[-1].append([y, 'WHATEVER']) 
    l3.append([x]) 
    l_aux = l1[:] 
    l_aux.remove(x[0]) 
for y in l_aux: 
    l3[-1].append([y, 'WHATEVER']) 
# Now, you have the elements you want grouped. 
# Last step: sort and flat the list: 
l3 = [y for x in l3 for y in sorted(x)] 
print '\n'.join(str(x) for x in l3) 
# ['A', 10] 
# ['B', 20] 
# ['C', 'WHATEVER'] 
# ['D', 5] 
# ['A', 15] 
# ['B', 30] 
# ['C', 10] 
# ['D', 15] 
# ['A', 8] 
# ['B', 'WHATEVER'] 
# ['C', 'WHATEVER'] 
# ['D', 'WHATEVER'] 
+0

это также не учитывает порядок, записи разделяются только тогда, когда он видит пару данных, которая использовалась до этого, поэтому вход 'l2 = [['A', 10], ['C', 5], ['B', 15], ['D', 30]] ', скорее всего, представляют две отдельные записи, но с вашим кодом он рассматривается только как один. –

+0

Тогда из-за этого он может быть сброшен с синхронизацией, вводят как 'l2 = [['A', 10], ['C', 5], ['B', 15], ['C', 30], ['A', 1], ['B', 2], ['C', 3], ['D', 4]] 'дает интересные результаты, но вряд ли будет правильным. –

+0

Nevermind, [OP только что подтвержден] (http://stackoverflow.com/questions/37636607/join-lists-with-repeated-values/37637873#comment62757118_37636607), что каждая запись будет содержать первый ключ, чтобы не было выключено -синхронный хаос с их прецедентом. –

1

Проблема с тем, как значениями словарей магазина. Словарь возьмет ваш ключ, используйте функцию __hash__, а затем сохраните это значение. Когда дело доходит до строк, две строки с одинаковым значением будут иметь тот же результат, когда __hash__ ed. Например

>>> a = "foo" 
>>> b = "foo" 
>>> a == b 
True 
>>> a.__hash__() 
-905768032644956145 
>>> b.__hash__() 
-905768032644956145 

Как вы можете видеть, что они оба имеют такое же значение, когда __hash__ ред. Поэтому, когда словарь пытается сохранить два одинаковых ключа, он будет переопределять предыдущее значение вместо создания нового ключа.

Глядя на ваш первый и второй пример, вы можете использовать список словарей вместо этого (Предполагая, что каждое значение начнется с "A" или "First Name").Таким образом, вы могли бы сделать что-то вроде этого:

dc = [] 
for s in l2: 
    if s[0] != "First Name": 
     dc[-1][s[0]] = s[1] 
    else: 
     dc.append({s[0]: s[1]}) 

Затем, чтобы получить "First Name" первого лица введенному из dc вы могли бы использовать это:

dc[0]["First Name"] 

Расширение это хранить их в качестве классы. Скажем, у нас есть класс называется Person:

class Person(object): 
    def __init__(self, personal_information): 
     super(Person, self).__init__() 
     self.first_name = personal_information["First Name"] 
     if "Last Name" in personal_information.keys(): 
      self.last_name = personal_information["Last Name"] 
     if "Email" in personal_information.keys(): 
      self.email = personal_information["Email"] 
     if "City" in personal_information.keys(): 
      self.city = personal_information["City"] 
    def __repr__(self): 
     # Just to make things look clean 
     return "Person("+self.first_name+")" 

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

people = [] 

for s in dc: 
    people.append(Person(s)) 

Если вы хотите получить доступ к имя первого лица:

>>> people 
[Person(John), Person(Jane)] 
>>> people[0].first_name 
'John' 

Типы структур данных зависят от вас.

+0

Спасибо за ваш ответ, теперь я понимаю, почему значения уникальны, а код, который вы опубликовали, работал очень хорошо - хотя он не показывал ключи без каких-либо значений, вы очень помогли! –

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