2013-05-01 118 views
8

我试图创建一个函数,它需要2个列表并返回只有两个列表有差异的列表。比较两个列表并仅打印差异? (XORing两个列表)

实施例:

a = [1,2,5,7,9] 
b = [1,2,4,8,9] 

结果应该打印[4,5,7,8]

功能迄今:

def xor(list1, list2): 
    list3=list1+list2 
    for i in range(0, len(list3)): 
     x=list3[i] 
     y=i 
     while y>0 and x<list3[y-1]: 
      list3[y]=list3[y-1] 
      y=y-1 
     list3[y]=x 

     last=list3[-1] 
    for i in range(len(list3) -2, -1, -1): 
     if last==list3[i]: 
      del list3[i] 
     else: 
      last=list3[i] 

    return list3 
print xor([1,2,5,7,8],[1,2,4,8,9]) 

第一个for循环排序它,第二个去除重复。问题是结果是 [1,2,4,5,7,8,9]不是[4,5,7,8],所以它不会完全删除重复?我可以添加什么来做到这一点。 我不能使用任何特殊的模块,.sort,set或任何东西,只是基本上循环。

回答

12

基本上你想添加一个元素到你的新列表,如果它存在于一个而不存在于另一个。这是一个紧凑的循环,可以做到这一点。对于在两个列表(与list1+list2将它们连接起来),我们添加元素,如果它不存在于其中的每个元素:

[a for a in list1+list2 if (a not in list1) or (a not in list2)] 

你可以将它通过元素作为明确的循环很容易转变成一个更unPythonic码你现在有,但老实说,我没有看到一个点(这不是问题):

def xor(list1, list2): 
    outputlist = [] 
    list3 = list1 + list2 
    for i in range(0, len(list3)): 
     if ((list3[i] not in list1) or (list3[i] not in list2)) and (list3[i] not in outputlist): 
      outputlist[len(outputlist):] = [list3[i]] 
    return outputlist 
+1

嗯,列表解析 – Patashu 2013-05-01 04:33:30

+0

我想我明白它在做什么,但是我会怎样使这成为一个完整的循环,并将该循环添加到原来的功能,或者是否会自行工作... – user2314520 2013-05-01 04:55:56

+0

这是一个单线程,它会执行您正在创建的功能...您通过list1 + list2循环元素x并且有两个if:1.如果list1中的元素使得flag1 = True,2.如果list2中的元素使得flag2 = True;如果(flag1和flag2)!= True且x不在outputlist中,则将其添加到outputlist。 – sashkello 2013-05-01 05:00:42

5

注:这是真的unpythonic,你已经整理两份名单后,只应作为一门功课的答案:)

,您可以通过执行以下操作找到重复:在

1)将迭代器A的开始和B

2)如果Aitr大于BITR更大,放置BITR的值在返回列表

3)否则,如果BITR大于Aitr更大之后前进BITR,放置Aitr的值在后推进Aiter返回列表

4)否则,你找到了一个副本,推进Aitr和BITR

+0

为什么你认为你的做法是unpythonic? – 2013-05-01 05:02:31

+0

@gnibbler看到盛的答案,我认为pythonic – Patashu 2013-05-01 05:03:04

+0

这依赖于所有可哈希元素。 (他们可能是) – 2013-05-01 05:06:35

10

使用一套更好

>>> a = [1,2,5,7,9] 
>>> b = [1,2,4,8,9] 
>>> set(a).symmetric_difference(b) 
{4, 5, 7, 8} 

由于@DSM,更好的一句话就是:

>>> set(a)^set(b) 

这些两个陈述是相同的。但后者更清晰。

更新:对不起,我没有看到最后的要求:不能使用set。据我看,@sashkello提供的解决方案是最好的。

+1

非家庭作业的好答案,但'我不能使用任何特殊模块,.sort,set或任何东西,只是基本循环。' – Patashu 2013-05-01 04:31:47

+2

为什么不简单地设置(a)^ set(b)',如果我们使用集合? – DSM 2013-05-01 04:33:14

+0

@DSM谢谢,你的建议比较好。我只是忘记了语法。 – Sheng 2013-05-01 04:33:53

1

简单,但也不是特别有效的:)

>>> a = [1,2,5,7,9] 
>>> b = [1,2,4,8,9] 
>>> [i for i in a+b if (a+b).count(i)==1] 
[5, 7, 4, 8] 

或用“只是循环“

>>> res = [] 
>>> for i in a+b: 
... c = 0 
... for j in a+b: 
... if i==j: 
... c += 1 
... if c == 1: 
... res.append(i) 
... 
>>> res 
[5, 7, 4, 8] 
+0

呵呵,不错! – sashkello 2013-05-01 05:05:20

3

此代码的工作原理假设你已经有了排序列表。它可以在线性时间内工作,而不像许多其他解决方案那样具有二次方。

def diff(sl0, sl1): 
    i0, i1 = 0, 0 
    while i0 < len(sl0) and i1 < len(sl1): 
     if sl0[i0] == sl1[i1]: 
      i0 += 1 
      i1 += 1 
     elif sl0[i0] < sl1[i1]: 
      yield sl0[i0] 
      i0 += 1 
     else: 
      yield sl1[i1] 
      i1 += 1 
    for i in xrange(i0, len(sl0)): 
     yield sl0[i] 
    for i in xrange(i1, len(sl1)): 
     yield sl1[i] 

print list(diff([1,2,5,7,9], [1,2,4,8,9])) 
+0

+1为线性解决方案。一般来说,[你可以调整它来接受任何迭代](http:// ideone。com/8bKqVB),本质上实现了[@ Patashu算法](http://stackoverflow.com/a/16312759/4279)。 – jfs 2013-05-02 01:39:57

2

试试这个,

a = [1,2,5,7,9] 
    b = [1,2,4,8,9] 
print set(a).symmetric_difference(set(b))