Проблема итерации Python! - PullRequest
       5

Проблема итерации Python!

4 голосов
/ 31 января 2010

У меня есть этот код здесь, он должен удалить общие буквы из обоих списков n1 и n2. Но когда я запускаю этот код, он запускается только один раз, поскольку он удаляет только «a» из n1 и n2 и не удаляет «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')

Хорошо, подождите, кажется, что это работает для указанных выше 2 имен, но когда у меня есть name1 = "naveen" и name2 = "darshana", это не работает!

Ответы [ 6 ]

5 голосов
/ 01 февраля 2010

Я предлагаю гораздо более простой подход:

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 по желанию.

Редактировать : как сейчас указывает ОП (в комментарии - пожалуйста, не забудьте отредактировать также вопрос , о, ОП!), Что он действительно хочет удалить только первое вхождение в каждом слове каждой общей буквы, необходимый алгоритм, конечно, совершенно другой. Простой подход (возможно, если длина слов не слишком велика):

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)
2 голосов
/ 01 февраля 2010

Более pythonic подход будет состоять в использовании set s и составлении списка.

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 s, чтобы вести подсчет случаев. Всякий раз, когда персонаж удаляется, соответствующий счетчик для другого имени уменьшается. Сложность все еще O (N).

Он печатает ['v', 'e', 'e', 'n', '0', '0'] и ['d', 'r', 's', 'h', 'a', 'a', '1', '1']. Это то, что вы хотели?

0 голосов
/ 02 февраля 2010

Вот некоторый вполне (ИМХО довольно элегантный) код, который работает в O (n). Если слово 1 имеет N вхождений буквы x, оно удаляет первые N x из слова 2 (и наоборот) - я думаю, это то, что вы хотите, но я могу ошибаться.

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')
0 голосов
/ 01 февраля 2010

Скорее всего, ваш код завершится ошибкой, потому что вы выводите обычные буквы из любой точки списка, но добавляете замены ("0" и "1") к концу списка. Они должны быть в положениях 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"

Во всяком случае, есть и другие «питонические» способы, которые уже показаны в других ответах.

РЕДАКТИРОВАТЬ: Протестировано и работает также с name1 = "naveen" / name2 = "darshana".

0 голосов
/ 01 февраля 2010

Ваш код может работать не так, как вы ожидаете, так как он удаляет парные буквы. Например, вы видите знак «а», затем вы удаляете оба слова из слов ...

0 голосов
/ 31 января 2010

Это работает здесь для меня. То есть, если я добавлю операторы печати таким образом:

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']
...