2015-02-22 4 views
3

Например, если у меня есть список следующим образом:Замена дубликатов элементов в списке на Python?

[3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1] 

Как я могу удалить дубликаты элементов и представляют собой один и тот же элемент, за которым следует число раз это повторяющейся? Результат:

[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3] 

Где 3 повторяются 6 раз ... -повторять 6 раз ... и так далее

+3

'[3,2] и' [3,3,3 ] 'сопоставить одно и то же, может ли это вызвать потенциальную проблему? – Akavall

ответ

6

Вы можете использовать itertools.groupby с функцией генератора здесь:

>>> from itertools import groupby            
>>> lst = [3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1] 
>>> def solve(seq): 
    for k, g in groupby(seq): 
     length = sum(1 for _ in g) 
     if length > 1: 
      yield k 
      yield length 
     else: 
      yield k 
...    
>>> list(solve(lst)) 
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3] 
0

Itertools - лучшее решение, но для другого применения без импорта мы можем использовать dict:

od = {} 

prev = None 
out = [] 
for ele in l: 
    if ele != prev and prev in od: 
     out.extend((prev, od[prev])) if od[prev] > 1 else out.append(prev) 
     od[prev] = 0 
    od.setdefault(ele, 0) 
    od[ele] += 1 
    prev = ele 
out.extend((ele, od[ele])) if od[ele] > 1 else out.append(ele) 
print(out) 
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3] 

Или в функции, используя более эффективный defaultdict, требуется больше памяти для хранения данных в Словаре, но это, вероятно, быстрее решение, используя GroupBy:

def grp1(l): 
    od = defaultdict(int) 
    prev = None 
    out = [] 
    for ele in l: 
     if ele != prev and prev in od: 
      out.extend((prev, od[prev])) if od[prev] > 1 else out.append(prev) 
      od[prev] = 0 
     od[ele] += 1 
     prev = ele 
    out.extend((ele, od[ele])) if od[ele] > 1 else out.append(ele) 
    return out 
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3] 

Интересно, что это хорошее количество быстрее, вероятно, потому что мы не должны перебрать каждый подсписка, чтобы получить Len:

In [33]: l = [choice(l) for _ in range(100000)] 

In [34]: timeit grp1(l) 
10 loops, best of 3: 23.9 ms per loop 

In [35]: timeit list(solve(l)) 
10 loops, best of 3: 33.9 ms per loop 

In [36]: list(solve(l)) == grp1(l) 
Out[36]: True 
-1

Альтернативное решение без использования itertools будет:

my_list = [3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1] 
new_list = [] 

new_list.append(my_list[0]) #adding first element 

count = 1 #variable for counting repeated elements 
i = 1 #iterator through list 

l = len(my_list) 

while i < l: 
    while i < l and my_list[i] == my_list[i-1]: 
     count +=1 
     i+=1 
    if count > 1: 
     new_list.append(count) 
     count = 1 #returning to original default value 
    else: 
     new_list.append(my_list[i]) 
     i+=1 

print(new_list) 
-1

В качестве альтернативного ответа вы можете просто играть с индексами, используя функцию рекурсии и iter:

def refiner(li,new=[]): 
    it=iter(li[1:]) 
    for i,j in enumerate(li[:-1],1): 
      curr=next(it) 
      if j!=curr : 
       if i>1: 
        new+=[j,i] 
        return refiner(li[i:],new) 

       elif i==len(li)-1:     
        new+=[j,curr] 
        return new 

       else: 
        new+=[j] 
        return refiner(li[i:],new) 

      elif i==len(li)-1: 
        new+=[j,i+1] 
        return new 

    return new 

DEMO:

l=[3, 3, 3, 3, 3, 3, 100, 1, 1, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 1, 1] 
print refiner(l) 
[3, 6, 100, 1, 6, 200, 3, 3, 100, 1, 3] 

l=[7, 7, 3, 9, 3, 3, 100, 1, 5, 1, 1, 1, 1, 200, 3, 3, 3, 100, 1, 7, 1] 
print refiner(l) 
[7, 2, 3, 9, 3, 2, 100, 1, 5, 1, 4, 200, 3, 3, 100, 1, 7, 1] 
+0

Надеюсь, что downvoter JUST немного позаботится о комментарии !!!!!!! – Kasramvd

Смежные вопросы