2015-09-09 22 views
5

Tôi có một danh sách mà từ đó tôi cần phải loại bỏ các giá trị trùng lặp và tổng các giá trị cột tương ứng. Danh sách này là:Xóa các giá trị trùng lặp và tổng các giá trị cột tương ứng

lst = [['20150815171000', '1', '2'], 
     ['20150815171000', '2', '3'], 
     ['20150815172000', '3', '4'], 
     ['20150815172000', '4', '5'], 
     ['20150815172000', '5', '6'], 
     ['20150815173000', '6', '7']] 

Bây giờ tôi cần phải đi qua qua danh sách và nhận được một cái gì đó ra như thế này:

lst2 = [['20150815171000', '3', '5'], 
     ['20150815172000', '12', '15'], 
     ['20150815173000', '6', '7']] 

Làm thế nào điều này có thể được thực hiện? Tôi đã cố gắng viết mã như hình dưới đây nhưng nó chỉ so sánh với các giá trị liên tiếp không, không phải tất cả các giá trị khớp.

lst2 = [] 
    ws = wr = power = 0 
    for i in range(len(lst)): 
     if lst[i][0] == lst[i+1][0]: 
      time = lst[i][0] 
      ws = (float(lst[i][1])+float(lst[i+1][1])) 
      wr = (float(lst[i][2])+float(lst[i+1][2]))  
     else: 
      time = lst[i][0] 
      ws = lst[i][1] 
      wr = lst[i][2] 
     lst2.append([time, ws, wr, power]) 

Bất kỳ ai cũng có thể cho tôi biết cách tôi có thể thực hiện việc này?

+0

Tạo một từ điển, bắt đầu với ví dụ '{'20150815171000': ['1', '2']}', sau đó chuyển trở lại danh sách sau – jonrsharpe

+0

Đầu ra mẫu của bạn có giá trị tổng là chuỗi, nhưng mã của bạn làm cho chúng nổi. Vì vậy, những gì bạn _really_ muốn, dây hoặc nổi? –

Trả lời

5

Tôi sẽ sử dụng itertools.groupby, nhóm dựa trên yếu tố đầu tiên trong danh sách bên trong. Vì vậy, trước tiên tôi sẽ sắp xếp danh sách dựa trên phần tử đầu tiên và sau đó dựa vào nó (Nếu danh sách đã được sắp xếp trên phần tử đó, thì bạn không cần sắp xếp lại, bạn có thể nhóm trực tiếp).

Ví dụ -

new_lst = [] 
for k,g in itertools.groupby(sorted(lst,key=lambda x:x[0]) , lambda x:x[0]): 
    l = list(g) 
    new_lst.append([k,str(sum([int(x[1]) for x in l])), str(sum([int(x[2]) for x in l]))]) 

Demo -

>>> import itertools 
>>> 
>>> lst = [['20150815171000', '1', '2'], 
...  ['20150815171000', '2', '3'], 
...  ['20150815172000', '3', '4'], 
...  ['20150815172000', '4', '5'], 
...  ['20150815172000', '5', '6'], 
...  ['20150815173000', '6', '7']] 
>>> 
>>> new_lst = [] 
>>> for k,g in itertools.groupby(sorted(lst,key=lambda x:x[0]) , lambda x:x[0]): 
...  l = list(g) 
...  new_lst.append([k,str(sum([int(x[1]) for x in l])), str(sum([int(x[2]) for x in l]))]) 
... 
>>> new_lst 
[['20150815171000', '3', '5'], ['20150815172000', '12', '15'], ['20150815173000', '6', '7']] 
+0

Cảm ơn rất nhiều người đàn ông đã làm việc. @ Anand S Kumar –

+2

Vui vì nó đã làm việc cho bạn. Tôi cũng muốn yêu cầu bạn chấp nhận câu trả lời, (bằng cách nhấp vào dấu tích ở bên trái của câu trả lời). Nó sẽ rất hữu ích cho cộng đồng. –

3

Bạn có thể sử dụng một từ điển để quản lý các mục duy nhất trong danh sách của bạn. Sau đó, bạn kiểm tra xem một khóa đã được chứa trong các phím của dict. Nếu khóa đã có trong dict sau đó thêm vào hiện tại, nếu không thêm một mục mới vào dict.

Hãy thử điều này:

#!/usr/bin/env python3 

sums = dict() 
for key, *values in lst: 
    try: 
     # add to an already present entry in the dict 
     sums[key] = [int(x)+y for x, y in zip(values, sums[key])] 
    except KeyError: 
     # if the entry is not already present add it to the dict 
     # and cast the values to int to make the adding easier 
     sums[key] = map(int, values) 

# build the output list from dictionary 
# also cast back the values to strings 
lst2 = sorted([[key]+list(map(str, values)) for key, values in sums.items()]) 

Các sorted trong dòng cuối cùng có thể là bắt buộc. Tùy thuộc vào việc bạn cần danh sách đầu ra để được sắp xếp bởi các phím dict hay không.

Lưu ý rằng thao tác này sẽ hoạt động với bất kỳ độ dài giá trị nào sau khóa.

+0

Đẹp được thực hiện – The6thSense

1

Giống như nhận xét về câu hỏi của bạn, tôi cũng khuyên bạn nên sử dụng từ điển để được trợ giúp. Tôi không phải là một lập trình viên tốt và có một cách chắc chắn tốt hơn, nhưng hoạt động này:

dct = dict() 
for x, y, z in lst: 
    if x not in dct: 
     dct[x] = [y, z] 
    else: 
     dct[x] = [str(int(dct[x][0]) + int(y)), str(int(dct[x][1]) + int(z))] 
lst2 = [] 
for k, v in dct.items(): 
    lst2.append([k, v[0], v[1]]) 

Bạn đang về cơ bản chỉ là lặp lại trên danh sách và thêm một mục mới vào từ điển, nếu số lượng truy nã (ví dụ như '2015081517100 ') không tồn tại, khác cập nhật các giá trị tương ứng. Cuối cùng bạn chỉ cần tạo một danh sách ra khỏi các kết quả trong từ điển

2

Ngoài ra, tôi sẽ đề nghị sử dụng pandas, khá thẳng về phía trước với groupbysum, đây là một cách để làm điều đó:

In [1]: import pandas as pd 

In [2]: df = pd.DataFrame(
[['20150815171000', '1', '2'], 
['20150815171000', '2', '3'], 
['20150815172000', '3', '4'], 
['20150815172000', '4', '5'], 
['20150815172000', '5', '6'], 
['20150815173000', '6', '7']], 
columns=['group', 'field1', 'field2']) 

In [3]: df 
Out[3]: 
      group field1 field2 
0 20150815171000  1  2 
1 20150815171000  2  3 
2 20150815172000  3  4 
3 20150815172000  4  5 
4 20150815172000  5  6 
5 20150815173000  6  7 

# need to convert from '1', '2'... to integer type 
In [4]: df['field1'] = df['field1'].astype('int') 

In [5]: df['field2'] = df['field2'].astype('int') 

# this groupby(to_group_field) and sum() can achieve what you want 
In [6]: df.groupby('group').sum() 
Out[6]: 
       field1 field2 
group 
20150815171000  3  5 
20150815172000  12  15 
20150815173000  6  7 

# convert to the list of lists format as you expected 
In [7]: df.groupby('group').sum().reset_index().values.tolist() 
Out[7]: 
[['20150815171000', 3, 5], 
['20150815172000', 12, 15], 
['20150815173000', 6, 7]] 

Hi vọng điêu nay co ich.

2

Làm sạch với lambdađược sắp xếp() bằng từ điển. Không có thư viện bổ sung.

lst = [['20150815171000', '1', '2'], 
     ['20150815171000', '2', '3'], 
     ['20150815172000', '3', '4'], 
     ['20150815172000', '4', '5'], 
     ['20150815172000', '5', '6'], 
     ['20150815173000', '6', '7']] 

dct = dict() 
for a, b, c in lst: 
    if a not in dct: 
     dct[a] = [b, c] 
    else: 
     dct[a] = map(lambda x, y: str(int(x)+int(y)), dct[a], [b,c]) 
lst2 = sorted([[k,v[0],v[1]] for k,v in dct.items()]) 

print(lst2) 

Out:

[['20150815171000', '3', '5'], 
['20150815172000', '12', '15'], 
['20150815173000', '6', '7']] 
Các vấn đề liên quan