代码之家  ›  专栏  ›  技术社区  ›  Jason Strimpel

从元组列表中获取最小唯一元组对

  •  1
  • Jason Strimpel  · 技术社区  · 11 月前

    考虑以下元组列表:

    transactions = [
        ('GBP.USD', '2022-04-29'),
        ('SNOW', '2022-04-26'),
        ('SHOP', '2022-04-21'),
        ('GBP.USD', '2022-04-27'),
        ('MSFT', '2022-04-11'),
        ('MSFT', '2022-04-21'),
        ('SHOP', '2022-04-25')
    ]
    

    我可以得到最短日期的元组,如下所示:

    min(transactions, key=lambda x: x[1])
    

    这将返回一个元组:

    ('MSFT', '2022-04-11')
    

    我需要返回任何重复项的最小日期以及所有唯一值。所以我的输出应该是这样的:

    [
        ('SNOW', '2022-04-26'),
        ('SHOP', '2022-04-21'),
        ('GBP.USD', '2022-04-27'),
        ('MSFT', '2022-04-11'),
    ]
    

    我该怎么做?

    5 回复  |  直到 11 月前
        1
  •  1
  •   Cem Koçak    11 月前

    解决方案1:

    min_dates = {}
    for item in transactions:
        key, date = item
        if key not in min_dates or date < min_dates[key]:
            min_dates[key] = date
    result = [(key, min_dates[key]) for key in min_dates]
    result.sort(key=lambda x: x[1])
    

    enter image description here

    解决方案2:

    from itertools import groupby
    # Sort transactions by key and then by date
    sorted_transactions = sorted(transactions)
    
    # Group transactions by key
    grouped_transactions = groupby(sorted_transactions, key=lambda x: x[0])
    
    # Construct final list of tuples with the minimum date for each key
    result = [(key, min(group, key=lambda x: x[1])[1]) for key, group in grouped_transactions]
    
    #print(result)
    # Prints : [('GBP.USD', '2022-04-27'), ('MSFT', '2022-04-11'), ('SHOP', '2022-04-21'), ('SNOW', '2022-04-26')]
    
        2
  •  1
  •   NikT    11 月前

    你应该能够做到:

    output = dict(reversed(sorted(transactions)))
    output = list(output.items())
    

    sorted 可以自动处理元组,并且由于您需要最小值,因此可以使用 reversed (而不是指定 key=lambda ... ).

    因为你的约会是 yyyy-mm-dd ,字符串排序应该正确。

    这是创建一个dict,并在每个键到达时用排序较少的值覆盖它。

        3
  •  0
  •   Hai Vu    11 月前

    我的计划是制作一本词典 {name: date} 其中日期是对应名称的最小(或最早)。

    transactions = [
        ('GBP.USD', '2022-04-29'),
        ('SNOW', '2022-04-26'),
        ('SHOP', '2022-04-21'),
        ('GBP.USD', '2022-04-27'),
        ('MSFT', '2022-04-11'),
        ('MSFT', '2022-04-21'),
        ('SHOP', '2022-04-25')
    ]
    
    earliest = {}
    for name, date in transactions:
        earliest.setdefault(name, date)
        if earliest[name] > date:
            earliest[name] = date
    out = list(earliest.items())
    

    out 则为:

    [('GBP.USD', '2022-04-27'),
     ('SNOW', '2022-04-26'),
     ('SHOP', '2022-04-21'),
     ('MSFT', '2022-04-11')]
    

    笔记

    • 这个 setdefault 方法很神奇:如果字典中不存在键,它会将键/值插入字典中。如果密钥确实存在,则不会插入(不执行任何操作)。
    • 设置默认值后,我将仅在值较小时更新该值
    • 有一次我造了字典 list(...items()) 会得到我们的结果。
    • 此功能不会改变 transactions 无论如何。
        4
  •  0
  •   Tony A    11 月前

    由于考虑太多,我的直觉反应导致我找到了下面的解决方案。注意,我并不认为这是最佳的。

    # Import pandas to leverage built-in query methods
    import pandas as pd
    
    # Define the test data, list of tuples
    transactions = [ ('GBP.USD', '2022-04-29'),
                     ('SNOW', '2022-04-26'),
                     ('SHOP', '2022-04-21'),
                     ('GBP.USD', '2022-04-27'),
                     ('MSFT', '2022-04-11'),
                     ('MSFT', '2022-04-21'),
                     ('SHOP', '2022-04-25') ]
    
    # Convert the test data into a pandas dataframe, columns can be named anything
    df = pd.DataFrame( transactions, columns=[ 'Symbol', 'Date' ] )
    
    # Convert the Date column into proper dates, very powerful option going forward
    df[ 'Date' ] = pd.to_datetime( df[ 'Date' ] )
    
    # Group the dataframe by the unique values in the Symbol column and reduce to instances where the minimum value appears in the Date column for a given unique value of the Symbol column
    df = df.groupby( 'Symbol' ).apply( lambda x: x.loc[ x.Date.idxmin() ] ).reset_index( drop=True )
    
    # Optional, convert the dataframe back into a list of tuples, maintains dates as Timestamps for future leveraging of pandas built in methods for date/time data
    transactions = list( df.itertuples( index=False, name=None ) )
    

    如果打印变量 df 在最后一次分配后,您将获得:

    print(df)
        Symbol       Date
    0  GBP.USD 2022-04-27
    1     MSFT 2022-04-11
    2     SHOP 2022-04-21
    3     SNOW 2022-04-26
    

    如果打印变量 transactions 在最后一次分配后,您将获得:

    print(transactions)
    [('GBP.USD', Timestamp('2022-04-27 00:00:00')), ('MSFT', Timestamp('2022-04-11 00:00:00')), ('SHOP', Timestamp('2022-04-21 00:00:00')), ('SNOW', Timestamp('2022-04-26 00:00:00'))]
    
        5
  •  0
  •   ThomasIsCoding    11 月前

    您可以使用 pandas 喜欢下面

    import pandas as pd
    list(pd.DataFrame(transactions).groupby(0).min().itertuples(name=None))
    

    应该给

    [('GBP.USD', '2022-04-27'),
     ('MSFT', '2022-04-11'),
     ('SHOP', '2022-04-21'),
     ('SNOW', '2022-04-26')]