繁体   English   中英

Python:在某些条件下将元组列表转换为字典

[英]Python: converting a list of tuples to dictionary with some conditions

我创建了一个像这样的列表:

Book = [(24, '2008-10-30', 'Start'), (24, '2008-12-20', 'End','sold'), 
 (25, '2009-01-01', 'Start'), (25, '2009-11-14', 'End', 'returned'),
 (26, '2010-04-03', 'Start'), (26, '2010-10-11', 'End', 'sold'),...]

我想将其转换成这样的字典:

bookDict = { 24: {'Start': '2008-10-30', 'End': '2008-12-20','reason':'sold'},
  25: {'Start': '2009-01-01', 'End': '2009-11-14','reason':'returned'},
  26: {'Start': '2010-04-03', 'End': '2010-10-11','reason':'sold'},...}

对于作为Book列表中元组的第一个值的字典中的每个键(这是一个代码),我希望有两个元组作为每个键的值。 其中一个与该特定代码的“开始”点有关,另一个与该特定代码的“结束”点有关。

我还有一个问题。 对于某些代码,有多个日期不同的“终点”。 我只想保留终点,并保留较晚的日期。 像这样的事情:

Book = [(24, '2008-10-30', 'Start'), (24, '2008-12-20', 'End', 'sold'), 
 (24, '2009-02-04', 'End', 'sold'), (24, '2009-11-25', 'End', 'sold')]

对于上面的示例字典应保留以下内容:

bookDict = { 24: {'Start': '2008-10-30', 'End': '2009-11-25','reason':'sold'},

谁能帮我吗?

您可以使用itertools.groupbyminmax

import itertools
def quantity_key(d):
  return list(map(int, d[1].split('-')))

Book = [(24, '2008-10-30', 'Start'), (24, '2008-12-20', 'End','sold'), (25, '2009-01-01', 'Start'), (25, '2009-11-14', 'End', 'returned'), (26, '2010-04-03', 'Start'), (26, '2010-10-11', 'End', 'sold')]
new_books = {a:list(b) for a, b in itertools.groupby(Book, key=lambda x:x[0])}
final_books = {a:{'Start':min(b, key=quantity_key)[1], 'End':max(b, key=quantity_key)[1], 'reason':max(b, key=quantity_key)[-1]} for a, b in new_books.items()}

输出:

{24: {'Start': '2008-10-30', 'End': '2008-12-20', 'reason': 'sold'}, 25: {'Start': '2009-01-01', 'End': '2009-11-14', 'reason': 'returned'}, 26: {'Start': '2010-04-03', 'End': '2010-10-11', 'reason': 'sold'}}

每个键有两个以上的值:

Book = [(24, '2008-10-30', 'Start'), (24, '2008-12-20', 'End', 'sold'), (24, '2009-02-04', 'End', 'sold'), (24, '2009-11-25', 'End', 'sold')]
new_books = {a:list(b) for a, b in itertools.groupby(Book, key=lambda x:x[0])}
final_books = {a:{'Start':min(b, key=quantity_key)[1], 'End':max(b, key=quantity_key)[1], 'reason':max(b, key=quantity_key)[-1]} for a, b in new_books.items()}

输出:

{24: {'Start': '2008-10-30', 'End': '2009-11-25', 'reason': 'sold'}}

这是一个满足两个条件的解决方案。

每当它收到新书ID时,它都会为其创建dict并在遇到list数据时将其填充。

对于多个结束条目,您的日期格式允许使用字符串比较来获取最新日期。

books = [(24, '2008-10-30', 'Start'), (24, '2008-12-20', 'End','sold'),
 (25, '2009-01-01', 'Start'), (25, '2009-11-14', 'End', 'returned'),
 (26, '2010-04-03', 'Start'), (26, '2010-10-11', 'End', 'sold'),
 (26, '2011-10-11', 'End', 'returned')] # The latest 'End' entry should be picked

bookDict = {}

for info in books:
    id_ = info[0]
    type_ = info[2]

    book = bookDict.setdefault(id_, {})

    if type_ == 'Start':
        book[type_] = info[1]

    elif type_ == 'End' and info[1] > book.get(type_, ''):
        book[type_] = info[1]
        book['reason'] = info[3]

输出:

bookDict
# {24: {'Start': '2008-10-30', 'End': '2008-12-20', 'reason': 'sold'},
#  25: {'Start': '2009-01-01', 'End': '2009-11-14', 'reason': 'returned'},
#  26: {'Start': '2010-04-03', 'End': '2010-10-11', 'reason': 'returned'}}

您可以执行以下操作:

for t in Book:
    index, date, marker, *rest = t
    entry = d.setdefault(index, {})
    end_date = entry.get("End", "1900-01-01")
    if marker == "Start" or date > end_date:
        entry[marker] = date
        if rest:
            entry["reason"] = rest[0]

尽管它可以适用于第二部分,但这仅回答了OP的第一部分问题。

您可以将collections.defaultdict用于O(n)解决方案:

book = [(24, '2008-10-30', 'Start'), (24, '2008-12-20', 'End','sold'), 
        (25, '2009-01-01', 'Start'), (25, '2009-11-14', 'End', 'returned'),
        (26, '2010-04-03', 'Start'), (26, '2010-10-11', 'End', 'sold')]

from collections import defaultdict

d = defaultdict(dict)

for key, date, *data in book:
    d[key][data[0]] = date
    if len(data) == 2:
        d[key]['reason'] = data[1]

另外,您可以捕获IndexError而不是测试元IndexError度:

for key, date, *data in book:
    d[key][data[0]] = date
    try:
        d[key]['reason'] = data[1]
    except IndexError:
        continue

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM