2010-03-29 98 views
4

我想比较不等长的嵌套列表。我只对每个子列表的第一个元素之间的匹配感兴趣。如果存在匹配,我希望将该匹配添加到另一个列表中,以便随后转换为制表符分隔的文件。以下是我与工作的一个例子:Python - 比较嵌套列表并将匹配追加到新列表中?

x = [['1', 'a', 'b'], ['2', 'c', 'd']] 

y = [['1', 'z', 'x'], ['4', 'z', 'x']] 

match = [] 

def find_match(): 
    for i in x: 
     for j in y: 
      if i[0] == j[0]: 
       match.append(j) 
      return match 

这将返回:

[['1', 'x'], ['1', 'y'], ['1', 'x'], ['1', 'y'], ['1', 'z', 'x']] 

难道是重新处理列表中删除重复很好的做法或可在此更简单的方式完成?

而且,是它更好地使用元组的元组和/或元组进行比较的目的是什么?

任何帮助,非常感谢。

问候, Seafoid。

+2

你是如何得到上述输出的?我只得到以下元素[['1','z','x']]作为输出。 – naivnomore 2010-03-29 15:00:29

回答

6
  • 使用装置获得的不重复的集合。

    • 您必须使用元组而不是列表作为项目,因为设置的项目必须是可哈希的。
  • 您发布的代码似乎没有生成您发布的输出。我不知道你应该如何从该输入中生成输出。例如,输出有'y',输入不是。

  • 我认为你的功能的设计可以大大改善。目前,您将xymatch定义为模块级别,并明确读取和变更它们。这不是你想要设计函数的方式 - 作为一般规则,函数不应该在全局级别上改变某些东西。它应该明确地传递它所需的一切,并返回一个结果,而不是隐式地接收信息并改变它自身之外的东西。

    我会改变

    x = some list 
    y = some list 
    match = [] 
    def find_match(): 
        for i in x: 
         for j in y: 
          if i[0] == j[0]: 
           match.append(j) 
        return match # This is the only line I changed. I think you meant 
           # your return to be over here? 
    find_match() 
    

    x = some list 
    y = some list 
    
    def find_match(x, y): 
        match = [] 
        for i in x: 
         for j in y: 
          if i[0] == j[0]: 
           match.append(j) 
        return match 
    match = find_match(x, y) 
    
  • 采取一个新的水平,去年的变化,我通常与同类发电机

    更换模式

    def f(...): 
        return_value = [] 
        for... 
         return_value.append(foo) 
        return return_value 
    

    def f(...): 
        for... 
         yield foo 
    

    这将使上述功能

    def find_match(x, y): 
        for i in x: 
         for j in y: 
          if i[0] == j[0]: 
           yield j 
    

    另一种方式来表达这种发电机的作用是与发电机表达(j for i in x for j in y if i[0] == j[0])

1
if i[1] == j[1] 

检查是否阵列的元件是相同的。你想要if i[0] == j[0]

否则,我觉得你的代码很可读,不一定会改变它。

2

我不知道我是否正确理解你的问题,但鉴于您的例子看来,你可能使用了错误的指标:

变化

if i[1] == j[1]: 

if i[0] == j[0]: 
+0

你是对的!感谢您指出了这一点。我编辑并纳入并显示输出。 – 2010-03-29 14:43:19

0

一个simplier表达应该在这里工作过:

list_of_lists = filter(lambda l: l[0][0] == l[1][0], zip(x, y)) 
map(lambda l: l[1], list_of_lists) 
+0

这比较了整个子列表,这似乎不是OP想要的。 – 2010-03-29 21:48:11

+0

另外,我不确定这是我所说的简单。我几乎总是发现使用list comprehensions比使用匿名函数的filter/map更好。例如,我认为'[suby subx,suby in zip(x,y)if subx == suby]'是(我认为)完全等价于你的代码,但比'filter'更好一些, '地图'版本。我认为'如果subx [0] == suby [0]]'suby in suby in suby in suby in suby in suby [suby]更接近于OP的代码。 – 2010-03-29 22:04:41

+0

@Mike我也喜欢列表解析功能,尽管功能接近程序偶尔会引诱我:-)。感谢指出错误,现在纠正。 – pajton 2010-03-29 22:22:10

1

您可以通过使用集合更简单地做到这一点。

set_x = set([i[0] for i in x]) 
set_y = set([i[0] for i in y]) 
matches = list(set_x & set_y) 
+0

谢谢丹尼尔 - 我不知道我可以在集合中指定索引。我认为该集只会返回列表中所有内容的完整匹配。 – 2010-03-29 14:44:49

+0

好主意[与集合一起工作]。然而,你应该强调,结果与原始程序的结果不同,关于排序和可能的重复值(根据结果的最终用途,这可能是也可能不重要)。 – mjv 2010-03-29 14:48:00

+0

@Seafoid:索引适用于x和y的子列表,而不适用于任何集合。 – mjv 2010-03-29 14:49:21