2010-12-12 91 views
0

检查我写了一个小程序:元组在Python

def check(xrr): 
    """ goes through the list and returns True if the list 
    does not contain common pairs, IE ([a,b,c],[c,d,e]) = true 
    but ([a,b,c],[b,a,c]) = false, note the lists can be longer than 2 tuples""" 
    x = xrr[:] 
    #sorting the tuples 
    sorted(map(sorted,x)) 
    for i in range(len(x)-1): 
     for j in range(len(x)-1): 
      if [x[i]] == [x[i+1]] and [x[j]] == [x[j+1]]: 
       return False 
    return True 

但它似乎没有工作的权利,这可能是一些非常基本的,但经过几天的努力和关闭,我不能真的似乎让我的头在错误的地方。

Thanx提前

+5

您仍然困惑元组和列表。另外,“似乎没有正确的工作”是一个100%无价值的错误报告 - 你得到了什么结果,你期望什么? – delnan 2010-12-12 14:30:53

+0

@delnan我认为预期的结果是在文档字符串中描述的,但我同意“仍然令人困惑的列表/元组”:) – khachik 2010-12-12 14:45:59

+0

如果函数会查找常见对(如果对意味着你'期望,即'对([1,2,3,4]) - > [(1,2),(2,3),(3,4)]'),那么就不会有'排序'那里。看看'[1,2,3,4]和[1,3,5,2]' – 2010-12-12 15:05:56

回答

1

与其他人提到的一样,代码有太多问题。我会试着解释我将如何实现这个功能。

这听起来像你想要做的事实际上是这样的:你从输入序列中产生一个对列表,并查看这些对之间是否有重复。当你制定这样的问题时,实施起来会更容易。

首先我们需要生成对。它可以通过多种方式来完成,你可能会做的一个是:

def pairs(seq): 
    ret = [] 
    # go to the 2nd last item of seq 
    for k in range(len(seq)-1): 
     # append a pair 
     ret.append((seq[k], seq[k+1])) 
    return ret 

现在,我们希望看到(A,B)和(B,A)和相同的元组,所以我们简单的元组进行排序:

def sorted_pairs(seq): 
    ret = [] 
    for k in range(len(seq)-1): 
     x,y = (seq[k], seq[k+1]) 
     if x <= y: 
      ret.append((x,y)) 
     else: 
      ret.append((y,x)) 
    return ret 

现在解决这个问题非常简单。我们只需要生成所有这些元组并将它们添加到集合中。一旦我们看到一对两次我们正在这样做:

def has_common_pairs(*seqs): 
    """ checks if there are any common pairs among any of the seqs """ 
    # store all the pairs we've seen 
    seen = set() 
    for seq in seqs: 
     # generate pairs for each seq in seqs 
     pair_seq = sorted_pairs(seq) 
     for pair in pair_seq: 
      # have we seen the pair before? 
      if pair in seen: 
       return True 
      seen.add(pair) 
    return False 

现在你想实现的功能是相当简单:

def check(xxr): 
    return not has_common_pairs(*xxr) 

PS:可以概括sorted_pa​​irs的函数,在任何类型的工作可迭代的,不仅仅是那些支持索引的。为了完整起见,我将在下面粘贴它,但您并不需要它,它很难理解:

def sorted_pairs(seq): 
    """ yield pairs (fst, snd) generated from seq 
     where fst <= snd for all fst, snd""" 
    it = iter(seq) 
    fst = next(it) 
    for snd in it: 
     if first <= snd: 
      yield fst, snd 
     else: 
      yield snd, fst 
     first = snd 
1

我会建议使用此一set

def check(xrr): 
    s = set() 
    for t in xrr: 
     u = tuple(sorted(t)) 
     if u in s: 
      return False 
     s.add(u) 
    return True 

这样一来,就不需要进行排序整个名单,并在第一个重复发现你停下来。

你的代码有几个错误。一个是sorted返回一个新的列表,并且你只是放弃返回值。另一个是你有两个嵌套循环你的数据,你只需要一个。这里是让你的方法工作的代码:

def check(xrr): 
    x = sorted(map(sorted,xrr)) 
    for i in range(len(x)-1): 
     if x[i] == x[i+1]: 
      return False 
    return True 

这可以缩短到

def check(xrr): 
    x = sorted(map(sorted,xrr)) 
    return all(a != b for a, b in zip(x[:-1], x[1:])) 

但请注意,我给第一个代码的效率会更高。

顺便说一句,Python中的列表是[1, 2, 3],而元组是(1, 2, 3)

+1

我不确定,但它似乎不应该工作,你不能将列表添加到一个集合(你会得到'列表是不可能的'或类似的东西)。 – khachik 2010-12-12 14:43:29

+0

@khachik:你说得对,谢谢。我修复它使用元组。 – 2010-12-12 14:47:35

0

sorted不改变源,它返回一个新的列表。

def check(xrr): 
    xrrs = map(sorted, xrr) 
    for i in range(len(xrrs)): 
     if xrrs[i] in xrrs[i+1:]: return False 
    return True 
0

我不知道这是对方的问题,但如果我理解正确的话,我会写:

def check(lst): 
    return any(not set(seq).issubset(lst[0]) for seq in lst[1:]) 

print check([(1, 2, 3), (2, 3, 5)]) # True 
print check([(1, 2, 3), (3, 2, 1)]) # False 
0

这里比较通用的解决方案,请注意,找到重复的,而不是'非重复“,这种方式更好,而不是使用不重复。

def has_duplicates(seq): 
    seen = set() 
    for item in seq: 
     if hasattr(item, '__iter__'): 
      item = tuple(sorted(item)) 
     if item in seen: 
      return True 
     seen.add(item) 
    return False 

这是一个寻找重复更通用的解决方案:

def get_duplicates(seq): 
seen = set() 
duplicates = set() 
for item in seq: 
    item = tuple(sorted(item)) 
    if item in seen: 
     duplicates.add(item) 
    else: 
     seen.add(item) 
return duplicates 

而且最好是找到重复的,而不是“不重复”,这样可以节省很多混乱。您比单用途功能更适合使用通用和可读的解决方案。