2012-01-05 40 views
17

Tôi có Python 2,7 từ điển cấu trúc sau dữ liệu (tôi không kiểm soát nguồn dữ liệu - xuất phát từ một hệ thống khác như là):Duplicates Loại bỏ Từ điển

 
{112762853378: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112762853385: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112760496444: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'] 
    }, 
112760496502: 
    {'dst': ['10.122.195.34'], 
    'src': ['4.3.2.1'] 
    }, 
112765083670: ... 
} 

Các phím từ điển sẽ luôn là duy nhất. Dst, src và bí danh có thể trùng lặp. Tất cả các bản ghi sẽ luôn có dst và src nhưng không phải mọi bản ghi sẽ nhất thiết phải có một bí danh như được thấy trong bản ghi thứ ba.

Trong dữ liệu mẫu, một trong hai bản ghi đầu tiên sẽ bị xóa (không quan trọng đối với tôi). Bản ghi thứ ba sẽ được coi là duy nhất vì mặc dù dst và src giống nhau nhưng thiếu bí danh.

Mục tiêu của tôi là xóa tất cả các bản ghi trong đó tất cả các bản ghi dst, src và bí danh đều bị trùng lặp - bất kể khóa nào.

Làm cách nào để tân binh thực hiện việc này?

Ngoài ra, sự hiểu biết hạn chế của tôi về Python diễn giải cấu trúc dữ liệu như một từ điển với các giá trị được lưu trữ trong từ điển ... một dict của dicts, là chính xác?

Trả lời

26

Bạn có thể đi mặc dù mỗi người trong số các mục (các cặp giá trị key) trong từ điển và thêm chúng vào một cuốn từ điển kết quả nếu giá trị là chưa có trong từ điển kết quả.

input_raw = {112762853378: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112762853385: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112760496444: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'] 
    }, 
112760496502: 
    {'dst': ['10.122.195.34'], 
    'src': ['4.3.2.1'] 
    } 
} 

result = {} 

for key,value in input_raw.items(): 
    if value not in result.values(): 
     result[key] = value 

print result 
+4

Đây là điểm khởi đầu tốt, nhưng tôi cảm thấy cần phải chỉ ra rằng nó sẽ chậm đối với các tập hợp dữ liệu lớn, bởi vì với mỗi vòng lặp, nó tạo ra một danh sách mới các giá trị và thực hiện tìm kiếm tuyến tính. – senderle

+0

Điều này làm việc với sự đơn giản và đẹp. –

+0

@senderle: Tôi đánh giá cao suy nghĩ và nhận xét của bạn về tốc độ và sẽ xem xét kỹ nếu cần. Bạn có quan tâm mở rộng câu trả lời này để tăng hiệu suất không? –

2

Một cách tiếp cận đơn giản là tạo một từ điển đảo ngược bằng cách ghép nối dữ liệu chuỗi trong mỗi từ điển bên trong làm khóa. Vì vậy, nói rằng bạn có những dữ liệu trên trong một cuốn từ điển, d:

>>> import collections 
>>> reverse_d = collections.defaultdict(list) 
>>> for key, inner_d in d.iteritems(): 
...  key_str = ''.join(inner_d[k][0] for k in ['dst', 'src', 'alias'] if k in inner_d) 
...  reverse_d[key_str].append(key) 
... 
>>> duplicates = [keys for key_str, keys in reverse_d.iteritems() if len(keys) > 1] 
>>> duplicates 
[[112762853385, 112762853378]] 

Nếu bạn không muốn có một danh sách các bản sao hoặc bất cứ điều gì như thế, nhưng chỉ muốn tạo ra một dict trùng lặp-ít hơn, bạn chỉ có thể sử dụng một từ điển thông thường thay vì một defaultdict và tái đảo ngược nó như vậy:

>>> for key, inner_d in d.iteritems(): 
...  key_str = ''.join(inner_d[k][0] for k in ['dst', 'src', 'alias'] if k in inner_d) 
...  reverse_d[key_str] = key 
>>> new_d = dict((val, d[val]) for val in reverse_d.itervalues()) 
+0

Rất phức tạp! – eyquem

1

Kể từ khi cách để tìm sự độc đáo trong sự tương ứng chính là sử dụng một từ điển, với các giá trị duy nhất mong muốn là chìa khóa, con đường để đi là để tạo ra một dict đảo ngược, nơi giá trị của bạn được cấu tạo là chìa khóa - sau đó tạo lại từ điển "bị đảo ngược" bằng kết quả trung gian.

dct = {112762853378: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112762853385: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'], 
    'alias': ['www.example.com'] 
    }, 
112760496444: 
    {'dst': ['10.121.4.136'], 
    'src': ['1.2.3.4'] 
    }, 
112760496502: 
    {'dst': ['10.122.195.34'], 
    'src': ['4.3.2.1'] 
    }, 
    } 

def remove_dups (dct): 
    reversed_dct = {} 
    for key, val in dct.items(): 
     new_key = tuple(val["dst"]) + tuple(val["src"]) + (tuple(val["alias"]) if "alias" in val else (None,)) 
     reversed_dct[new_key] = key 
    result_dct = {} 
    for key, val in reversed_dct.items(): 
     result_dct[val] = dct[val] 
    return result_dct 

result = remove_dups(dct) 
+0

Rất phức tạp – eyquem

0
from collections import defaultdict 

dups = defaultdict(lambda : defaultdict(list)) 

for key, entry in data.iteritems(): 
    dups[tuple(entry.keys())][tuple([v[0] for v in entry.values()])].append(key) 

for dup_indexes in dups.values(): 
    for keys in dup_indexes.values(): 
     for key in keys[1:]: 
      if key in data: 
       del data[key] 
+0

Quá phức tạp – eyquem

1
dups={} 

for key,val in dct.iteritems(): 
    if val.get('alias') != None: 
     ref = "%s%s%s" % (val['dst'] , val['src'] ,val['alias'])# a simple hash 
     dups.setdefault(ref,[]) 
     dups[ref].append(key) 

for k,v in dups.iteritems(): 
    if len(v) > 1: 
     for key in v: 
      del dct[key] 
+0

Phải cập nhật thông tin này. Nên làm việc ngay bây giờ, nếu tôi hiểu câu hỏi một cách chính xác. – joel3000

2

Một dict biến ngược lại:

>>> import pprint 
>>> 
>>> data = { 
... 112762853378: 
... {'dst': ['10.121.4.136'], 
...  'src': ['1.2.3.4'], 
...  'alias': ['www.example.com'] 
... }, 
... 112762853385: 
... {'dst': ['10.121.4.136'], 
...  'src': ['1.2.3.4'], 
...  'alias': ['www.example.com'] 
... }, 
... 112760496444: 
... {'dst': ['10.121.4.136'], 
...  'src': ['1.2.3.4'] 
... }, 
... 112760496502: 
... {'dst': ['10.122.195.34'], 
...  'src': ['4.3.2.1'] 
... }, 
... } 
>>> 
>>> keep = set({repr(sorted(value.items())):key 
...    for key,value in data.iteritems()}.values()) 
>>> 
>>> for key in data.keys(): 
...  if key not in keep: 
...   del data[key] 
... 
>>> 
>>> pprint.pprint(data) 
{112760496444L: {'dst': ['10.121.4.136'], 'src': ['1.2.3.4']}, 
112760496502L: {'dst': ['10.122.195.34'], 'src': ['4.3.2.1']}, 
112762853378L: {'alias': ['www.example.com'], 
       'dst': ['10.121.4.136'], 
       'src': ['1.2.3.4']}} 
+0

Tốt nhưng phức tạp trong quan điểm của tôi – eyquem

+0

Có vẻ như điều này sẽ đếm '{'src': ['1.2.3.4'], 'dst': ['10.121.3.1236']}' và '{'src': ['10.121 .3.1236 '],' dst ': [' 1.2.3.4 ']} 'làm bản sao của nhau ... – senderle

+0

@senderle. Vâng phát hiện! Sửa lỗi bây giờ, FWIW. Tôi có lẽ cũng nên chỉ ra rằng giải pháp này, mặc dù nhỏ gọn, là khá kém hiệu quả so với một số người khác. – ekhumoro

2
input_raw = {112762853378: {'dst': ['10.121.4.136'], 
          'src': ['1.2.3.4'], 
          'alias': ['www.example.com'] }, 
      112762853385: {'dst': ['10.121.4.136'], 
          'src': ['1.2.3.4'], 
          'alias': ['www.example.com'] }, 
      112760496444: {'dst': ['10.121.4.299'], 
          'src': ['1.2.3.4'] }, 
      112760496502: {'dst': ['10.122.195.34'], 
          'src': ['4.3.2.1'] }, 
      112758601487: {'src': ['1.2.3.4'], 
          'alias': ['www.example.com'], 
          'dst': ['10.121.4.136']}, 
      112757412898: {'dst': ['10.122.195.34'], 
          'src': ['4.3.2.1'] }, 
      112757354733: {'dst': ['124.12.13.14'], 
          'src': ['8.5.6.0']},    
      } 

for x in input_raw.iteritems(): 
    print x 
print '\n---------------------------\n' 

seen = [] 

for k,val in input_raw.items(): 
    if val in seen: 
     del input_raw[k] 
    else: 
     seen.append(val) 


for x in input_raw.iteritems(): 
    print x 

kết quả

(112762853385L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.136'], 'alias': ['www.example.com']}) 
(112757354733L, {'src': ['8.5.6.0'], 'dst': ['124.12.13.14']}) 
(112758601487L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.136'], 'alias': ['www.example.com']}) 
(112757412898L, {'src': ['4.3.2.1'], 'dst': ['10.122.195.34']}) 
(112760496502L, {'src': ['4.3.2.1'], 'dst': ['10.122.195.34']}) 
(112760496444L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.299']}) 
(112762853378L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.136'], 'alias': ['www.example.com']}) 

--------------------------- 

(112762853385L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.136'], 'alias': ['www.example.com']}) 
(112757354733L, {'src': ['8.5.6.0'], 'dst': ['124.12.13.14']}) 
(112757412898L, {'src': ['4.3.2.1'], 'dst': ['10.122.195.34']}) 
(112760496444L, {'src': ['1.2.3.4'], 'dst': ['10.121.4.299']}) 

Các dữ kiện rằng giải pháp này crea tes đầu tiên một danh sách input_raw.iteritems() (như trong câu trả lời của Cox của Andrew) và yêu cầu một danh sách ngày càng tăng thấy là những hạn chế.
Nhưng không thể tránh đầu tiên (sử dụng iteritems() không hoạt động) và thứ hai ít nặng hơn việc tạo lại danh sách result.values ​​() từ danh sách ngày càng tăng kết quả cho mỗi lượt của vòng lặp.

-2
example = { 
    'id1': {'name': 'jay','age':22,}, 
    'id2': {'name': 'salman','age': 52,}, 
    'id3': {'name':'Ranveer','age' :26,}, 
    'id4': {'name': 'jay', 'age': 22,}, 
} 
for item in example: 
    for value in example: 
     if example[item] ==example[value]: 
      if item != value: 
       key = value 
       del example[key] 
print "example",example   
+0

Vui lòng định dạng câu trả lời của bạn bằng nút '{}', định dạng các vấn đề bằng Python. Và nó là một ý tưởng rất xấu để sửa đổi danh sách hoặc từ điển, trong khi lặp lại chúng. Rất tệ. – MrT

+0

Chào mừng bạn đến với StackOverflow: nếu bạn đăng mã, XML hoặc mẫu dữ liệu, hãy đánh dấu những dòng đó trong trình soạn thảo văn bản và nhấp vào nút "mẫu mã" ({}) trên thanh công cụ trình soạn thảo hoặc sử dụng Ctrl + K trên bàn phím của bạn định dạng và cú pháp làm nổi bật nó! – WhatsThePoint

Các vấn đề liên quan