【问题标题】:Removing duplicate records from a Python list从 Python 列表中删除重复记录
【发布时间】:2015-03-31 22:16:26
【问题描述】:

我正在从 URL 获取数据并对该数据进行一些处理。我现在已经到了需要消除重复项的地步。下面是我的程序的输出。

{u'Price': 133.84, u'@Number': u'1', u'Mw': 10} 
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15} 
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10} 
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10} 
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9} 
{u'Price': 133.84, u'@Number': u'1', u'Mw': 10} 
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15} 
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10} 
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10} 
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9} 
{u'Price': 133.84, u'@Number': u'1', u'Mw': 10} 
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15} 
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10} 
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10} 
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9}

我希望这是我的输出:

{u'Price': 133.84, u'@Number': u'1', u'Mw': 10} 
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15} 
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10} 
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10} 
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9}

@Number 可以介于 1-7 之间。解决这个问题的最佳方法是什么?我是否需要获取 @Number 的最大值,然后打印与我的最大值一样多的行?

【问题讨论】:

  • 1) 相同的条目是否在所有方面都相同?也就是说,所有的键值对都相同吗? 2)你关心结果的顺序吗?
  • 它们完全一样。 @Number 基本上告诉我我有多少独特的记录。保持秩序很重要。
  • 等等,你只想保留总共七行,每个@Number的值一个?这与比较整行完全不同。是哪个?

标签: python list duplicates iteration


【解决方案1】:

你可以为你已经看过的那一个保留一组:

seen=set()
data=[]
for e in input:
    if e["@Number"] not in seen:
        seen.add(e["@Number"])
        data.append(e)

>>> data
[{u'Price': 133.84, u'@Number': u'1', u'Mw': 10}, {u'Price': 139.09, u'@Number': u'2', u'Mw': 15}, {u'Price': 144.34, u'@Number': u'3', u'Mw': 10}, {u'Price': 148.53, u'@Number': u'4', u'Mw': 10}, {u'Price': 152.52, u'@Number': u'5', u'Mw': 9}]

如果您的数据始终井井有条,并且打印最大值后您的行将完成,您可以这样做:

>>> input[0:max(int(e) for e in (d['@Number'] for d in input))]
[{u'Price': 133.84, u'@Number': u'1', u'Mw': 10}, {u'Price': 139.09, u'@Number': u'2', u'Mw': 15}, {u'Price': 144.34, u'@Number': u'3', u'Mw': 10}, {u'Price': 148.53, u'@Number': u'4', u'Mw': 10}, {u'Price': 152.52, u'@Number': u'5', u'Mw': 9}]

【讨论】:

  • 问题是我的输出没有列表格式。每行在读取 URL 时都会被推出。是否可以从我的输出中列出一个列表?我尝试了 list[output] 但后来我得到 [u'Price', u'@Number', u'Mw'] 没有数据值。
  • 对带有集合的数据使用 for 循环。完毕。公开。假设它是可迭代的……数据是怎么来的?
  • 对不起..我不确定你的意思.. :(
  • 你说它不是一个字典列表——好的。您正在阅读_____的这些 dics?
  • 我使用 requests.get(url)。然后我做了很多数据操作,最终得到上面的输出。你是什​​么意思:“在你的数据上使用 for 循环”?
【解决方案2】:

使用OrderedDict 来维持秩序,并使用u'@Number' 作为键,仅当u'@Number' 尚未在out dict 中时才添加。

l=[{u'Price': 133.84, u'@Number': u'1', u'Mw': 10},
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15},
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10},
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10},
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9},
{u'Price': 133.84, u'@Number': u'1', u'Mw': 10},
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15},
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10},
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10},
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9},
{u'Price': 133.84, u'@Number': u'1', u'Mw': 10},
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15},
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10},
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10},
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9}
]

from collections import OrderedDict
od = OrderedDict()
for d in l:
    num =  d["@Number"]
    if num not in od:
        od[num] = d

print(list(od.values())

[{u'@Number': u'1', u'Mw': 10, u'Price': 133.84},
{u'@Number': u'2', u'Mw': 15, u'Price': 139.09},
{u'@Number': u'3', u'Mw': 10, u'Price': 144.34},
{u'@Number': u'4', u'Mw': 10, u'Price': 148.53},
{u'@Number': u'5', u'Mw': 9, u'Price': 152.52}]

如果在您的示例中始终保证订单,您可以在发现重复的 "@Number" 时简单地中断:

for d in l:
    num = d["@Number"]
    if num not in od:
        od[num] = d
    else:
         break

如果你想使用max:

from itertools import islice
from operator import itemgetter

# for @Number" > 9 use lambda
#  mx = int(max(l, key=lambda x: int(x["@Number"]))["@Number"])
mx = int(max(l, key=itemgetter("@Number"))["@Number"])
print(list(islice(l,None,mx)))

【讨论】:

  • 如果有大于 1 位的字符串,您在最大中断中转换为 int 的方法应注意...
  • @dawg,OP 声明字符串始终为 1-7,如果不是,则 lambda 将作为转换为 int 的键
  • 我提到它是为了未来的 SO 浏览器,它附带一个排序字典列表,其中该字段可能不是数字的 ascii 值的巧合,也是它的最大值。多于一位数字或负值会破坏代码。它确实适用于 OP 所述的有限情况 - 已确认。
  • @dawg,不用担心,我添加了一个 lambda,它适用于任何正数或负数。
  • 保持冷静并继续前进 ;-)
【解决方案3】:

这个程序按你的要求做:

data = [
{u'Price': 133.84, u'@Number': u'1', u'Mw': 10} ,
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15} ,
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10} ,
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10} ,
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9} ,
{u'Price': 133.84, u'@Number': u'1', u'Mw': 10} ,
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15} ,
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10} ,
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10} ,
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9} ,
{u'Price': 133.84, u'@Number': u'1', u'Mw': 10} ,
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15} ,
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10} ,
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10} ,
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9},
]

result = []
for item in data:
    if item not in result:
        result.append(item)
for item in result:
    print item

输出:

{u'Price': 133.84, u'@Number': u'1', u'Mw': 10}
{u'Price': 139.09, u'@Number': u'2', u'Mw': 15}
{u'Price': 144.34, u'@Number': u'3', u'Mw': 10}
{u'Price': 148.53, u'@Number': u'4', u'Mw': 10}
{u'Price': 152.52, u'@Number': u'5', u'Mw': 9}

【讨论】:

    【解决方案4】:

    另一种可能性,使用 OrderedDict:

    from collections import OrderedDict
    
    l = [{u'Price': 133.84, u'@Number': u'1', u'Mw': 10}, 
    {u'Price': 139.09, u'@Number': u'2', u'Mw': 15} ,
    {u'Price': 144.34, u'@Number': u'3', u'Mw': 10} ,
    {u'Price': 148.53, u'@Number': u'4', u'Mw': 10} ,
    {u'Price': 152.52, u'@Number': u'5', u'Mw': 9} ,
    {u'Price': 133.84, u'@Number': u'1', u'Mw': 10} ,
    {u'Price': 139.09, u'@Number': u'2', u'Mw': 15} ,
    {u'Price': 144.34, u'@Number': u'3', u'Mw': 10} ,
    {u'Price': 148.53, u'@Number': u'4', u'Mw': 10} ,
    {u'Price': 152.52, u'@Number': u'5', u'Mw': 9} ,
    {u'Price': 133.84, u'@Number': u'1', u'Mw': 10} ,
    {u'Price': 139.09, u'@Number': u'2', u'Mw': 15} ,
    {u'Price': 144.34, u'@Number': u'3', u'Mw': 10} ,
    {u'Price': 148.53, u'@Number': u'4', u'Mw': 10} ,
    {u'Price': 152.52, u'@Number': u'5', u'Mw': 9}]
    
    od = OrderedDict()
    
    for d in l:
        od[d["@Number"]] = d
    
    
    print(od)
    

    结果是:

    OrderedDict([('1', {'@Number': '1', 'Price': 133.84, 'Mw': 10}), ('2', {'@Number': '2', 'Price': 139.09, 'Mw': 15}), ('3', {'@Number': '3', 'Price': 144.34, 'Mw': 10}), ('4', {'@Number': '4', 'Price': 148.53, 'Mw': 10}), ('5', {'@Number': '5', 'Price': 152.52, 'Mw': 9})])
    

    在字典中,@Number 用作键。并且因为它是一个 OrderedDict,所以保留了原始列表中 Numbers 的顺序。

    【讨论】:

    • 这实际上也会搞砸订单
    • @PadraicCunningham 怎么样?这是它们在原始列表中出现的顺序。
    • 这为您提供了最后一组唯一性;他的示例具有列表中的第一组唯一性...
    • @dawg 在这个例子中没关系。第一个或最后一个唯一性的价格和 Mws 值相同。
    • 是的——我想他们是。无论如何,这里的一些方法提供了第一组唯一性;其他人,比如你的,最后一组。我想 OP 需要指定哪个对他的数据是正确的。干杯。
    【解决方案5】:

    您可以制作一个以 Price @Number 和 Mw 作为键的字典。然后检查新项目是否已经在字典中。

    def combine(L):
        results = {}
        for item in L:
            key = (item["Price"], item["@Number"],item["Mw"])
            if key not in results:  # combine them
                results[key] = item
        return results.values()
    

    输出

    {u'Price': 148.53, u'@Number': u'4', u'Mw': 10}
    {u'Price': 139.09, u'@Number': u'2', u'Mw': 15}
    {u'Price': 152.52, u'@Number': u'5', u'Mw': 9}
    {u'Price': 144.34, u'@Number': u'3', u'Mw': 10}
    {u'Price': 133.84, u'@Number': u'1', u'Mw': 10}
    

    【讨论】:

      【解决方案6】:

      如果您的数据确实如您所描述的那样,并且您想排除相同的三元组,那么显而易见的解决方案是将它们转换为一个集合。由于顺序很重要,您可以使用 collections.OrderedDict 代替虚拟值 True

      您首先需要将数据转换为元组,因为字典不能用作字典键:

      mytuples = [ tuple(x["Price"], x["@Number"], x["Mw"]) for x in mydata
      

      (或者只是将您的数据构建为元组开始)。

      然后:

      from collections import OrderedDict
      unique = OrderedDict((tup, True) for tup in mytuples) 
      

      您现在可以使用unique.keys() 按出现顺序检索您的三胞胎。

      【讨论】:

        猜你喜欢
        • 2016-01-07
        • 2019-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-11
        • 1970-01-01
        • 2015-01-03
        相关资源
        最近更新 更多