【问题标题】:Compare lists Python比较列表 Python
【发布时间】:2015-02-12 23:05:42
【问题描述】:

我有一个比较的两个 CSV 文件,并且有这样的数据(我不确定这些是否称为列表或列表列表或其他内容):

来自文件 1:x =

['BDCA0', '01', '25', 'A']
['PPTR', '02', '14', 'A']
['ABCD1', '07', '14', 'A']

来自文件 2:y =

['ABCD1', '00', '4', 'A']
['BDCA0', '04', '25', 'A']
['PPTR', '02', '14', 'A']

我想比较这两个并打印差异但保持第一个元素不变。我想要的输出是:

['ABCD1', '07', '14', 'A']
['ABCD1', '00', '4', 'A']
['BDCA0', '01', '25', 'A']
['BDCA0', '04', '25', 'A']

我尝试做[a for a in x if a not in y] + [a for a in y if a not in x],但它给了我垃圾。

【问题讨论】:

  • 行的顺序是否相同?
  • @Jan-PhilipGehrcke 不一定!
  • 那么你需要先对行进行排序,或者第一列是从两个文件中匹配行的关键列?
  • 这不是关键。我已经用它作为匹配的键,这些是结果列表。我现在只想要这些列表中的差异,将第一列保留在输出中。 @Marcin
  • 这只是:cat x y | sort | uniq?

标签: python list csv compare


【解决方案1】:

你可以看看使用 pandas。这似乎与您正在尝试做的事情非常匹配。例如,

import pandas as pd


x1 = [['h1', 'h2', 'h3', 'h4'],
['ABCD1', '07', '14', 'A'],
['BDCA0', '01', '25', 'A'],
['PPTR', '02', '14', 'A']]

x2 = [['h1', 'h2', 'h3', 'h4'],
['ABCD1', '00', '4', 'A'],
['BDCA0', '04', '25', 'A'],
['PPTR', '02', '14', 'A']]




df1 = pd.DataFrame(x1[1:], columns=x1[0]).set_index('h1')
df2 = pd.DataFrame(x2[1:], columns=x2[0]).set_index('h1')

print(df1[df1!=df2])
print(df2[df1!=df2])


        h2   h3   h4
h1                  
ABCD1   07   14  NaN
BDCA0   01  NaN  NaN
PPTR   NaN  NaN  NaN
        h2   h3   h4
h1                  
ABCD1   00    4  NaN
BDCA0   04  NaN  NaN
PPTR   NaN  NaN  NaN

是的,我知道它与您的输出不完全匹配,因为我不确定您如何准确比较行。但我认为使用 pandas 可能会很有用,尤其是当你必须经常做类似的事情时。

【讨论】:

  • 如果我们没有标题行怎么办?
  • 比熊猫自己的列数,例如0,1,2,3。键列(即索引)相同。
  • 这条线会有什么变化? df1 = pd.DataFrame(x1[1:], columns=x1[0]).set_index('h1')
  • 如果您不想要任何自定义标头或索引,只需执行 df1 = pd.DataFrame(x1)
  • 我需要索引,但有时我没有标题。
【解决方案2】:

执行此操作的方式不那么复杂——例如,您可以创建一个作为两个列表交集的列表,然后创建一个仅包含那些不在交集中的元素的列表——但这实现了相同的目标.

#!/usr/bin/env python

from operator import itemgetter
import json

with open("x.json") as f:
    x = json.load(f)
with open("y.json") as f:
    y = json.load(f)
def diff(a, b):
   return [aa for aa in a if aa not in b]
def notintersect(a,b):
   return sorted(diff(a,b) + diff(b,a), key=itemgetter(0))

for row in notintersect(x,y):
   print"[",
   sep=''
   for col in row:
      print sep + repr(str(col)),
      sep=','
   print ']'

输出:

[ 'ABCD1' ,'07' ,'14' ,'A' ]
[ 'ABCD1' ,'00' ,'4' ,'A' ]
[ 'BDCA0' ,'01' ,'25' ,'A' ]
[ 'BDCA0' ,'04' ,'25' ,'A' ]

要将文件中的数据转换为可用格式:

#!/usr/bin/env bash

(
    read LINE
    echo "[$LINE" | tr "'" '"'
    while read LINE
    do
      echo ",$LINE"| tr "'" '"'
    done
    echo "]"
) < "$1" > "$1.json"

(您还需要手动删除该“标题”评论,但假设这是唯一的评论,那不会有太大的开销。这还假设您的数据不包含任何单引号或双引号,这 - 基于示例您提供的数据 - 似乎是一个合理的假设。)

【讨论】:

  • 我的列表不是这样的结构。它们正是我发布问题的方式,而您的答案不适用于我的列表:(
  • 哦...那么,您的文件实际上包含方括号和单引号吗?在这种情况下,我认为它们不算作 CSV。我只是假设你已经加载了它们。 :P
  • 好的,我有一个适合你的方法。给我一秒钟。
【解决方案3】:

我不知道您是否可以确定每个列表中的第一个元素都相同,但如果您这样做(并且您可以腾出内存来复制一对新数据结构中的数据),字典可以很适合你:

x = [
     ['BDCA0', '01', '25', 'A'],
     ['PPTR', '02', '14', 'A'],
     ['ABCD1', '07', '14', 'A']
    ]

y = [
     ['ABCD1', '00', '4', 'A'],
     ['BDCA0', '04', '25', 'A'],
     ['PPTR', '02', '14', 'A']
    ]

dx = dict([(xx[0], xx[1:]) for xx in x])
dy = dict([(yy[0], yy[1:]) for yy in y])

for k, v in dx.items():
    if v != dy[k]:
        print [k] + v
        print [k] + dy[k]

给予:

['ABCD1', '07', '14', 'A']
['ABCD1', '00', '4', 'A']
['BDCA0', '01', '25', 'A']
['BDCA0', '04', '25', 'A']

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多