Python迭代问题!

时间:2010-01-31 20:41:59

标签: python iteration

我这里有这个代码,它应该从列表n1和n2中删除常用字母。但是当我运行这个代码时,它只运行一次,因为它只从n1和n2中删除'a'并且不会删除'k'。

只是为了澄清这段代码应该只能用于2个单词。

name1 = "abdjek"
name2 = "doarhsnk"

n1l = list(name1)
n2l = list(name2)

for i in range(len(n1l)):
   for j in range(len(n2l)):
         if n1l[i] == n2l[j]:
               n1l.pop(i)
               n2l.pop(j)
               n1l.append('0')
               n2l.append('1')

好的等等,它似乎适用于上述两个名字但是当我有name1 =“naveen”而name2 =“darshana”时它不起作用!

6 个答案:

答案 0 :(得分:5)

我建议采用一种更简单的方法:

def removecommon(name1, name2):
  common = set(name1).intersection(name2)
  res1 = ''.join(n for n in name1 if n not in common)
  res2 = ''.join(n for n in name2 if n not in common)
  return res1, res2

n1, n2 = removecommon('naveen', 'darshana')
print n1, n2

根据需要发出vee drsh

修改:正如现在指定的OP(在评论中 - 请记住编辑你的问题,哦OP!)他实际上只想删除在每个普通字母的每个单词中出现第一次,所需的算法当然是完全不同的。一种简单的方法(如果单词的长度不是太高,则可行):

def removefirstcommon(name1, name2):
  common = set(name1).intersection(name2)
  n1 = list(name1)
  for c in common: n1.remove(c)
  n2 = list(name2)
  for c in common: n2.remove(c)
  return ''.join(n1), ''.join(n2)

一个更精细的方法(对于正常长度的单词来说速度慢)对于极长的单词会更快(因为以下是O(N)而前者的O(N平方)):

def removefirstcommonlongwords(name1, name2):
  common = set(name1).intersection(name2)
  def mustrem(c, copycom):
    res = c not in copycom
    copycom.discard(c)
    return res
  cop = set(common)
  n1 = [c for c in name1 if mustrem(c, cop)]
  n2 = [c for c in name2 if mustrem(c, common)]
  return ''.join(n1), ''.join(n2)

答案 1 :(得分:2)

更多 pythonic 方法是使用set和列表推导。

name1 = "naveen"; name2 = "darshana"

name1_set=set(name1)
name2_set=set(name2)

clean1=[x for x in  name1 if x not in name2_set]
clean2=[x for x in name2 if x not in name1_set]

clean1.extend(['0']*(len(name1)-len(clean1)))
clean2.extend(['1']*(len(name2)-len(clean2)))

print clean1,clean2

set为我们提供了O(1)查找,从而通过将O(N)代替O(N ^ 2)使整个过程更快。

编辑:根据您之后的评论,发生次数很重要,这是考虑到这一点的更新版本。

name1 = "naveen"; name2 = "darshana"

count1={}
count2={}


for x in name1:
    count1[x]=count1.get(x,0)+1

for x in name2:
    count2[x]=count2.get(x,0)+1

def remove_dups(name,count,null):
    clean=[]
    for x in name:
        if count.get(x,0):
            count[x]-=1
        else:
            clean.append(x)
    clean.extend([null]*(len(name)-len(clean)))
    return clean

clean1=remove_dups(name1,count2,'0')
clean2=remove_dups(name2,count1,'1')

print clean1,clean2

它使用dict来保持发生次数。每当删除一个字符时,另一个名称的相应计数就会减少。复杂性仍然是O(N)。

它会打印['v', 'e', 'e', 'n', '0', '0']['d', 'r', 's', 'h', 'a', 'a', '1', '1']。那是你想要的吗?

答案 2 :(得分:0)

它在这里为我工作。也就是说,如果我这样添加print语句:

name1 = "abdjek"
name2 = "doarhsnk"

n1l = list(name1)
n2l = list(name2)

print "Lists before loop:"
print n1l
print n2l

for i in range(len(n1l)):
    for j in range(len(n2l)):
        if n1l[i] == n2l[j]:
           n1l.pop(i)
           n2l.pop(j)
           n1l.append('0')
           n2l.append('1')

print "Lists after loop:"
print n1l
print n2l

字符'a','d'和'k'全部删除:

> python test.py 
Lists before loop:
['a', 'b', 'd', 'j', 'e', 'k']
['d', 'o', 'a', 'r', 'h', 's', 'n', 'k']
Lists after loop:
['b', 'j', 'e', '0', '0', '0']
['o', 'r', 'h', 's', 'n', '1', '1', '1']

答案 3 :(得分:0)

您的代码可能无法正常工作,因为它正在删除成对的字母。例如,你看到a,然后从你的单词中删除两个......

答案 4 :(得分:0)

您的代码很可能失败,因为您从列表中的任何位置弹出常用字母,但将替换(“0”和“1”)附加到列表的 end 。它们应分别位于 i j 的位置。

所以循环应该看起来像这样:

for i in range(len(n1l)):
   for j in range(len(n2l)):
         if n1l[i] == n2l[j] and n1l[i] not in ("0", "1"):
               print "common letter ", n1l[i]
               # Replace i-th and j-th element
               n1l[i] = "0"
               n2l[j] = "1"

无论如何,还有更多“pythonic”方式,已经在其他答案中显示出来了。

编辑:对name1 = "naveen" / name2 = "darshana"进行了测试和工作。

答案 5 :(得分:0)

这是一些在O(n)中运行的完全(恕我直言,相当优雅)的代码。如果单词1出现字母x的N次,它会从单词2中删除前N个(反之亦然) - 我认为这就是你想要的,但我可能是错的。

from collections import defaultdict

def build(s, chars_s, chars_t):
    """Return characters of s, with duplicate characters from t removed."""
    for i, char in enumerate(s):
        indexes_s, indexes_t = chars_s[char], chars_t[char]
        if len(indexes_s) > len(indexes_t) and i >= indexes_s[len(indexes_t)]:
            yield char

def rm_dup(a, b):
    """Pairwise remove duplicate letters in a and b."""
    chars_a, chars_b = defaultdict(list), defaultdict(list)
    for i, char in enumerate(a): chars_a[char].append(i)
    for i, char in enumerate(b): chars_b[char].append(i)
    return (''.join(build(a, chars_a, chars_b)),
            ''.join(build(b, chars_b, chars_a)))

print rm_dup('naveen', 'darshana')