قم بتعيين قائمتين في قائمة واحدة من القواميس

StackOverflow https://stackoverflow.com/questions/244438

  •  04-07-2019
  •  | 
  •  

سؤال

تخيل أن لدي قوائم بايثون هذه:

keys = ['name', 'age']
values = ['Monty', 42, 'Matt', 28, 'Frank', 33]

هل هناك طريقة مباشرة أو على الأقل بسيطة لإنتاج قائمة القواميس التالية؟

[
    {'name': 'Monty', 'age': 42},
    {'name': 'Matt',  'age': 28},
    {'name': 'Frank', 'age': 33}
]
هل كانت مفيدة؟

المحلول

وهنا هي الطريقة البريدي

def mapper(keys, values):
    n = len(keys)
    return [dict(zip(keys, values[i:i + n]))
            for i in range(0, len(values), n)]

نصائح أخرى

وانها ليست جميلة ولكن هنا على الخطوط الملاحية المنتظمة واحد باستخدام قائمة الفهم، والرمز البريدي والتنقل:

[dict(zip(keys, a)) for a in zip(values[::2], values[1::2])]

وسيلة البكم، ولكن ذلك يأتي فورا إلى ذهني:

def fields_from_list(keys, values):
    iterator = iter(values)
    while True:
        yield dict((key, iterator.next()) for key in keys)

list(fields_from_list(keys, values)) # to produce a list.

وzip لا تقريبا ما تريد؛ للأسف، بدلا من ركوب الدراجات قائمة أقصر، فإنه يكسر. ربما هناك وظيفة ذات الصلة التي دورات؟

$ python
>>> keys = ['name', 'age']
>>> values = ['Monty', 42, 'Matt', 28, 'Frank', 33]
>>> dict(zip(keys, values))
{'age': 42, 'name': 'Monty'}

و/ تحرير: أوه، كنت ترغب في قائمة من <م> ديكت . الأعمال التالية (بفضل بيتر، وكذلك):

from itertoos import cycle

keys = ['name', 'age']
values = ['Monty', 42, 'Matt', 28, 'Frank', 33]

x = zip(cycle(keys), values)
map(lambda a: dict(a), zip(x[::2], x[1::2]))

في الجواب بواسطة كونراد رودولف

الرمز البريدي يفعل ما تريد تقريبًا؛لسوء الحظ، بدلاً من تدوير القائمة الأقصر، فإنها تنكسر.ربما هناك وظيفة ذات صلة تدور؟

وإليك طريقة:

keys = ['name', 'age']
values = ['Monty', 42, 'Matt', 28, 'Frank', 33]
iter_values = iter(values)
[dict(zip(keys, iter_values)) for _ in range(len(values) // len(keys))]

لن أسميها Pythonic (أعتقد أنها ذكية جدًا)، ولكنها قد تكون ما أبحث عنه.

ليس هناك فائدة من ركوب الدراجات keys القائمة باستخدام itertools.cycle(), ، لأن كل اجتياز keys يتوافق مع إنشاء قاموس واحد.

يحرر: إليك طريقة أخرى:

def iter_cut(seq, size):
    for i in range(len(seq) / size):
        yield seq[i*size:(i+1)*size]

keys = ['name', 'age']
values = ['Monty', 42, 'Matt', 28, 'Frank', 33]
[dict(zip(keys, some_values)) for some_values in iter_cut(values, len(keys))]

هذا أكثر بيثونية:هناك وظيفة مساعدة قابلة للقراءة ولها غرض واضح، وبقية التعليمات البرمجية تتدفق منها بشكل طبيعي.

إليك توجهي بسيط. ويبدو أن تكون قريبة من فكرة أنCheery كان إلا أنني تدمير قائمة الدخل.

def pack(keys, values):
  """This function destructively creates a list of dictionaries from the input lists."""
  retval = []
  while values:
    d = {}
    for x in keys:
      d[x] = values.pop(0)
    retval.append(d)
  return retval

وبعد آخر محاولة، ربما غباء من أول واحد:

def split_seq(seq, count):
    i = iter(seq)
    while True:
        yield [i.next() for _ in xrange(count)]

>>> [dict(zip(keys, rec)) for rec in split_seq(values, len(keys))]
[{'age': 42, 'name': 'Monty'},
 {'age': 28, 'name': 'Matt'},
 {'age': 33, 'name': 'Frank'}]

ولكن الامر متروك لكم لاتخاذ قرار سواء كان ذلك غباء.

[dict(zip(keys,values[n:n+len(keys)])) for n in xrange(0,len(values),len(keys)) ]

وUG-LEEE. أنا أكره أن أرى التعليمات البرمجية التي يشبه ذلك. ولكن يبدو الصحيح.

def dictizer(keys, values):
   steps = xrange(0,len(values),len(keys))
   bites = ( values[n:n+len(keys)] for n in steps)
   return ( dict(zip(keys,bite)) for bite in bites )

ومع ذلك القبيح قليلا، ولكن أسماء تساعد في جعل الشعور بها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top