2017-10-06 33 views
1

我有一个元组列表,它包含公司的日期和名称。公司可以拥有信息列出了多个日期:Python:获取每个公司的最近日期

[(Company A, datetime.date(1980,1,30)), 
    (Company A, datetime.date(1990,1,30)), 
    (Company B, datetime.date(1990,1,30)), 
    (Company B, datetime.date(2000,1,30))] 

我想要做的,是有一个列表,只包括每家公司可用的最新日期,即结果:

[(Company A, datetime.date(1990,1,30)), 
    (Company B, datetime.date(2000,1,30))] 

有任何想法吗?

+3

您到目前为止尝试过哪些方面,我们需要使用代码。 [如何创建一个最小,完整和可验证的示例](https://stackoverflow.com/help/mcve) –

+0

我认为这是一些列表理解,但我有点失落。可能以[(i,j)为开头,如果我是公司,如果max(j)为set(i)] – pinkfairyprincess

+0

我们不想为您编写代码。那里的乐趣在哪里?但我建议你看看'reduce'。 – dashmug

回答

3

怎么样使用从itertools一个groupby,然后取最大值:

import datetime 
x = [('Company A', datetime.date(1980,1,30)), 
    ('Company A', datetime.date(1990,1,30)), 
    ('Company B', datetime.date(1990,1,30)), 
    ('Company B', datetime.date(2000,1,30))] 

import itertools 
out = [] 
for k,g in itertools.groupby(sorted(x, key = lambda y: y[0]), lambda y: y[0]): 
    out.append(max(g, key = lambda y:y[1])) 

out 
[('Company A', datetime.date(1990, 1, 30)), 
('Company B', datetime.date(2000, 1, 30))] 
+0

'groupby'的问题是它期望同一组的成员是连续的。将list(groupby('abcabcabc'))'的结果与'list(groupby('aaabbbccc'))'的结果进行比较。如果不能保证列表中的元素按公司分组,则您建议的方案将失败。在你的具体例子中,如果你交换'x'中的中间两个元素,你最终会在'out'中包含4个元素。 – jacg

+0

好点,我们可以在这种情况下添加排序,请参阅编辑 – jeremycg

+0

排序将解决语义问题,但确实会增加解决方案的算法复杂度,从* O(n)*到* O(n log n) *。所以,如果你的数据集足够大,并且你在程序中经常做到这一点,那么它可能会比找到线性解决方案花费更多。 – jacg

2

你也可以使用一个字典...

data = [('Company A', '1980,1,30'), 
    ('Company A', '1990,1,30'), 
    ('Company B', '1990,1,30'), 
    ('Company B', '2000,1,30')] 

datadict = { a:b for a,b in data } 

for a, b in data: 
    datadict[a] = max(b, datadict[a]) 

print(datadict) 
+0

通过使用'dict'作为一个变量,你正在隐藏内置的'dict':阴影内置插件不是一个好主意。 – jacg

+0

如果您真的需要结果列表中的对,那么只需在Python 2中使用'datadict.items()',或者在Python 3中使用'list(datadict.items())'。 – jacg

1

下面是使用一个例子reduce()

import datetime 

company_dates = [ 
    ('Company A', datetime.date(1980,1,30)), 
    ('Company A', datetime.date(1990,1,30)), 
    ('Company B', datetime.date(1990,1,30)), 
    ('Company B', datetime.date(2000,1,30)), 
] 

def reducer(acc, company_date): 
    try: 
    acc[company_date[0]] = max(acc[company_date[0]], company_date[1]) 
    except KeyError: 
    acc[company_date[0]] = company_date[1] 

    return acc 

sorted = reduce(reducer, company_dates, {}) 

print sorted.items() 

下面是使用不同功能的另一种替代解决方案:

import datetime 
import operator 

company_dates = [ 
    ('Company A', datetime.date(1980,1,30)), 
    ('Company A', datetime.date(1990,1,30)), 
    ('Company B', datetime.date(1990,1,30)), 
    ('Company B', datetime.date(2000,1,30)), 
] 

sorted = sorted(company_dates, key=operator.itemgetter(0, 1), reverse=True) 
unique = set([company_date[0] for company_date in sorted]) 
top = [next(c for c in sorted if c[0] == company) for company in unique] 

print top