python基础语法学习记录之数据结构和算法(2)

本文介绍了Python中处理字典和序列的高效方法,包括查找字典的共同元素、删除序列中的重复项、统计序列中元素的出现次数、按字段排序字典列表等实用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考cookbook的学习笔记

1. 查找两字典的相同点

a = {
'x' : 1,
'y' : 2,
'z' : 3
} 
b= {
'w' : 10,
'x' : 11,
'y' : 2
}

Python3支持如下操作:

# Find keys in common
a.keys() & b.keys() # { 'x', 'y' }
# Find keys in a that are not in b
a.keys() - b.keys() # { 'z' }
# Find (key,value) pairs in common
a.items() & b.items() # { ('y', 2) }

# Make a new dictionary with certain keys removed
c = {key:a[key] for key in a.keys() - {'z', 'w'}}
# c is {'x': 1, 'y': 2}

Python2中可用集合进行操作获得如上结果:

>>> c = set(a)
>>> c
set(['y', 'x', 'z'])
>>> d = set(b)
>>> d
set(['y', 'x', 'w'])
>>> c&d
set(['y', 'x'])
>>> c-d
set(['z'])
>>> e = set(a.items())
>>> e
set([('z', 3), ('y', 2), ('x', 1)])
>>> f = set(b.items())
>>> e&f
set([('y', 2)])
>>> c = set(a)
>>> c
set(['y', 'x', 'z'])
>>> d = set(b)
>>> d
set(['y', 'x', 'w'])
>>> c&d
set(['y', 'x'])
>>> c-d
set(['z'])
>>> e = set(a.items())
>>> e
set([('z', 3), ('y', 2), ('x', 1)])
>>> f = set(b.items())
>>> e&f
set([('y', 2)])
>>> g = c-{'z','w'}
>>> g
set(['y', 'x'])
>>> g = {key:a[key] for key in g}
>>> g
{'y': 2, 'x': 1}
>>>

2. 删除序列相同元素并保持顺序

序列中元素为hashable:
可用生成器解决:

def dedupe(items): 
    seen = set() 
    for item in items: 
        if item not in seen: 
            yield item 
            seen.add(item)
举例:
>>> a = [1, 5, 2, 1, 9, 1, 5, 10] 
>>> list(dedupe(a)) 
[1, 5, 2, 9, 10] 
>>>

序列中元素不可hashable:

def dedupe(items, key=None): 
    seen = set() 
    for item in items: 
        val = item if key is None else key(item) 
        if val not in seen: 
            yield item 
            seen.add(val)
举例:
>>> a = [ {'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}] 
>>> list(dedupe(a, key=lambda d: (d['x'],d['y']))) 
[{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}] 
>>> list(dedupe(a, key=lambda d: d['x'])) 
[{'x': 1, 'y': 2}, {'x': 2, 'y': 4}] 
>>>

hashable说明:
键和值得对应关系不可变,表示hashable。包括int,float,str,元组
键和值得对应关系可变,表示unhashable。包括list,set,dict,对象

3. 序列中出现次数最多的元素

最戳的办法可以自己写个迭代进行计算。以下介绍collections.Counter 类:

words = [ 
'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes', 
'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the', 
'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into', 
'my', 'eyes', "you're", 'under' 
]
from collections import Counter 
word_counts = Counter(words) 
# 出现频率最高的3个单词 
top_three = word_counts.most_common(3) 
print(top_three) 
# Outputs [('eyes', 8), ('the', 5), ('look', 4)]

说明:
作为输入, Counter 对象可以接受任意的 hashable 序列对象。 在底层实现上,一个 Counter 对象就是一个字典,将元素映射到它出现的次数上。比如:

>>> word_counts['not'] 
1 
>> word_counts['eyes'] 
8 
>>>

Counter有一个和数学运算相结合的特性:

morewords = ['why','are','you','not','looking','in','my','eyes']
>>> a = Counter(words) 
>>> b = Counter(morewords) 
>>> a 
Counter({'eyes': 8, 'the': 5, 'look': 4, 'into': 3, 'my': 3, 'around': 2, 
"you're": 1, "don't": 1, 'under': 1, 'not': 1}) 
>>> b 
Counter({'eyes': 1, 'looking': 1, 'are': 1, 'in': 1, 'not': 1, 'you': 1, 
'my': 1, 'why': 1}) 
>>> # Combine counts 
>>> c = a + b 
>>> c 
Counter({'eyes': 9, 'the': 5, 'look': 4, 'my': 4, 'into': 3, 'not': 2, 
'around': 2, "you're": 1, "don't": 1, 'in': 1, 'why': 1, 
'looking': 1, 'are': 1, 'under': 1, 'you': 1}) 
>>> # Subtract counts 
>>> d = a - b 
>>> d 
Counter({'eyes': 7, 'the': 5, 'look': 4, 'into': 3, 'my': 2, 'around': 2, 
"you're": 1, "don't": 1, 'under': 1}) 
>>>

4. 通过某个关键字排序一个字典列表

operator 模块的 itemgetter 函数:

rows = [ 
{'fname': 'Brian', 'lname': 'Jones', 'uid': 1003}, 
{'fname': 'David', 'lname': 'Beazley', 'uid': 1002}, 
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, 
{'fname': 'Big', 'lname': 'Jones', 'uid': 1004} 
]
举例:
from operator import itemgetter 
rows_by_fname = sorted(rows, key=itemgetter('fname')) 
rows_by_uid = sorted(rows, key=itemgetter('uid')) 
print(rows_by_fname) 
print(rows_by_uid)
输出:
[{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'}, 
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'}, 
{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'}, 
{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'}] 

[{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'}, 
{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'}, 
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'}, 
{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'}]

itemgetter() 函数可以支持多个keys:

rows_by_lfname = sorted(rows, key=itemgetter('lname','fname')) 
print(rows_by_lfname)
[{'fname': 'David', 'uid': 1002, 'lname': 'Beazley'}, 
{'fname': 'John', 'uid': 1001, 'lname': 'Cleese'}, 
{'fname': 'Big', 'uid': 1004, 'lname': 'Jones'}, 
{'fname': 'Brian', 'uid': 1003, 'lname': 'Jones'}]

itemgetter() 可用 lambda 表达式代替:

rows_by_fname = sorted(rows, key=lambda r: r['fname']) 
rows_by_lfname = sorted(rows, key=lambda r: (r['lname'],r['fname']))

5. 通过某个字段将记录分组

itertools.groupby() 函数:

rows = [ 
{'address': '5412 N CLARK', 'date': '07/01/2012'}, 
{'address': '5148 N CLARK', 'date': '07/04/2012'}, 
{'address': '5800 E 58TH', 'date': '07/02/2012'}, 
{'address': '2122 N CLARK', 'date': '07/03/2012'}, 
{'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'}, 
{'address': '1060 W ADDISON', 'date': '07/02/2012'}, 
{'address': '4801 N BROADWAY', 'date': '07/01/2012'}, 
{'address': '1039 W GRANVILLE', 'date': '07/04/2012'}, 
]

from operator import itemgetter 
from itertools import groupby 
# Sort by the desired field first 
rows.sort(key=itemgetter('date')) 
# Iterate in groups 
for date, items in groupby(rows, key=itemgetter('date')): 
    print(date) 
    for i in items: 
        print(' ', i)

输出结果:
07/01/2012 
{'date': '07/01/2012', 'address': '5412 N CLARK'} 
{'date': '07/01/2012', 'address': '4801 N BROADWAY'} 
07/02/2012 
{'date': '07/02/2012', 'address': '5800 E 58TH'} 
{'date': '07/02/2012', 'address': '5645 N RAVENSWOOD'} 
{'date': '07/02/2012', 'address': '1060 W ADDISON'} 
07/03/2012 
{'date': '07/03/2012', 'address': '2122 N CLARK'} 
07/04/2012 
{'date': '07/04/2012', 'address': '5148 N CLARK'} 
{'date': '07/04/2012', 'address': '1039 W GRANVILLE'} 

自己实现:

from collections import defaultdict 
rows_by_date = defaultdict(list) 
for row in rows: 
    rows_by_date[row['date']].append(row)

6. 过滤序列元素

对于一个序列,按照某种规则进行提取
举例:

>>> mylist = [1, 4, -5, 10, -7, 2, 3, -1] 
>>> [n for n in mylist if n > 0] 
[1, 4, 10, 2, 3] 
>>> [n for n in mylist if n < 0] 
[-5, -7, -1] 
>>>

这种方法存在的缺陷在于,当输入序列相当大的时候,会导致结果也相当大,以至于占用大量内存。对此,可以使用生成器表达式迭代产生过滤元素。
举例:

>>> pos = (n for n in mylist if n > 0) 
>>> pos 
<generator object <genexpr> at 0x1006a0eb0> 
>>> for x in pos: 
... print(x) 
... 
1 
4 
10 
2 
3 
>>>

当过滤规则相对比较复杂的时候,可以使用内建filter函数。filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。
举例:

values = ['1', '2', '-3', '-', '4', 'N/A', '5'] 
def is_int(val): 
    try: 
        x = int(val) 
        return True 
    except ValueError: 
        return False 
ivals = list(filter(is_int, values)) 
print(ivals) 
# Outputs ['1', '2', '-3', '4', '5']
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值