python数据结构

Posted by 琼脂糖 on September 18, 2019

Python数据结构:列表,数组,生成器,元祖等。

1. list列表

列表对象是可直接相加的。相当于两个列表合并。

combined = zeros + letters

list(range(10))可以将literable转换成list

letter[::2] 每两个元素返回 lette[;;-1]倒序

list解包

全部提取

numbers = [1, 2, 3]
first, second, third = numbers

仅提取前两个

numbers = [1, 2, 3, 4, 4, 4, 4, 4, 4]
first, second, *other = numbers

for循环和enumerate连用

提取列表index和内容。

letters = ["a", "b", "c"]

for index, letter in enumerate(letters):
    print(index, letter)

增删列表内容

letter = ["a", "b", "c"]

# Add
letters.append("d")
letters.insert(0, "-")

# Remove
letters.pop(0)
letters.remove("b")
del letters[0:3]
letters.clear()
print(letters)

找items

print(letters.count("d"))
if "d" in letters:
    print(letters.index("d"))

排序

numbers = [3, 51, 2, 8, 6]
numbers.sort(reverse=True)
sorted(numbers)

sorted返回新的列表。sort在原列表修改

对复杂的列表如何定义基于什么排序(下面代码可以用匿名函数简化)

items = [
    ("Product1", 10),
    ("Product2", 9),
    ("Product3", 12)]
def sort_item(item):
    return item[1]
items.sort(key=sort_item

##2. lambda,map,filter,列表推导式
匿名函数语法:lambda parameters:expression

items = [
    ("Product1", 10),
    ("Product2", 9),
    ("Product3", 12)
]
prices = list(map(lambda item: item[1], items))
#[10, 9, 12]
items.sort(key=lambda item: item[1])
print(items)
#[('Product2', 9), ('Product1', 10), ('Product3', 12)]

map

map(func,literable :返回的是一个map对象,可以用list转换成列表

map(func, *iterables) :对iterables中的每个参数执行函数,得到一个map对象,是一个iterator。

filter

filter(func,literable)
func返回布尔值

items = [
    ("Product1", 10),
    ("Product2", 9),
    ("Product3", 12)
]
x = list(filter(lambda item: item[1]  10, items))
print(x)
# [('Product1', 10), ('Product3', 12)]

list comprehension:列表推导式

推荐用这个。而不是map和filter

语法:[expression for item in items]

# map和等同的列表推导式
prices = list(map(lambda item: item[1], items))
prices = [item[1] for item in items]
# filter和等同的列表推导式
filtered = list(filter(lambda item: item[1]  10, items))
filtered = [item for item in items if item[1]  10]
# else
new = [0 if item[1]10 else 0 for item in items]

3. zip

zip(iter1 [,iter2 [...]]) --> zip object

Return a zip object whose .next() method returns a tuple where the i-th element comes from the i-th iterable argument.

list1 = [1, 2, 3]
list2 = [10, 20, 30]
print(list(zip("abc", list1, list2)))
#[('a', 1, 10), ('b', 2, 20), ('c', 3, 30)]

4. stacks&queues

stack:LIFO 后进先出

queues:FIFO 先进先出

from collections import deque
queue = deque([])
queue.append(1)
queue.append(2)
queue.append(3)
queue.popleft()
print(queue)
if not queue:
    print("empty")

5. tuple:括号可省略,但要有逗号

和list的区别是,tuple不可修改

tuple可用于快速交换变量的值

x, y = y, x

6. array

指定类别。当处理十万级的数据时可用

from array import array

numbers = array("i", [1, 2, 3])

i:signed integer

7. set

集合 大括号 是unordered list,没有重复值,没有index

numbers = [1, 1, 2, 3, 4]
first = set(numbers)
second = {1, 5}

print(first | second)
print(first & second)
print(first - second)
print(first ^ second)

if 1 in first:
    print("yes")

8. 字典

下面两种创建中, 第二种方法更好

point = {"x": 1, "y": 2}
point = dict(x=1, y=2)

get method: 如果不存在则默认返回null。如果设定第二个参数,则返回第二个参数的值 print(point.get("a", 0))

删除某个成员 del point["x"]

循环字典

for key in point:
    print(key, point[key])

items返回的是tuple,因此可以直接解包

for key,value in point.items():
    print(key, value)

comprehension: 列表,set,字典都可以用推导式

values = {x: x * 2 for x in range(5)}

defaltdict

https://www.jianshu.com/p/bbd258f99fd3

from collections import defaultdict
STATS = defaultdict(lambda: defaultdict(str))

一个这样的字典,如何按key sort呢

s = sorted(STATS.items())
for i in s:
    print(i[0])
    

s成为一个排序后的list,list的每个成员是一个tuple,包括之前字典的key和value。

9. 生成器

用在创建的列表特别的大。不会将全部的值存在内存中,而是每个循环生成一个值。

和列表生成器在写法上的区别就是一个是中括号,一个是圆括号。

generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。正常使用是有for循环。

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。把print改成yield就可以

def fib(x):
    n = 0
    a, b = 0, 1
    while n < x:
        yield b
        a, b = b, a+b
        n = n + 1
g = fib(6)

print(next(g))

for i in g:
    print(i)
    

这里的fib就是一个生成器,g是一个生成器对象。可用for循环访问全部的结果。

code:单位bytes

from sys import getsizeof
values = (x * 2 for x in range(100000))
print("gen:", getsizeof(values))
values = [x * 2 for x in range(100000))
print("list:", getsizeof(values))
#gen: 120
#list: 824464

杨辉三角

import operator

def triangles():
    L1 = [1]
    while True:
        yield L1
        L_former = [0] + L1
        L_last = L1 + [0]
        L1 = list(map(operator.add, L_former, L_last))

tri = triangles()
print(next(tri))
print(next(tri))
print(next(tri))
print(next(tri))
print(next(tri))
#[1]
#[1, 1]
#[1, 2, 1]
#[1, 3, 3, 1]
#[1, 4, 6, 4, 1]

生成器函数需要一个loop,每次yield一个loop。

map函数,实现两个list的相加运算。这里用到了operator模块。

10. 解包:星号 可用于解包任何literable

numbers = [1, 2, 3]
print(*numbers)
print(1, 2, 3)

创建list将range obj解包。

values = list(range(5))
values = [*range(5)]
print(values)

字典用两个星号。重复的key,后面的覆盖前面的

first = {"x": 1}
second = {"x": 10, "y": 2}
combined = {**first, **second, "z": 1}
print(combined)

11. 练习

  1. 目的:一个句子中最常出现的字符
  2. key-value pair用字典。列表推导式,重复的元素,后面的覆盖前面的。
    字典是unordered list,因此不能用sort。需要将其转换成tuple list。
    pprint 可以选择一行显示几个
  3. code
from pprint import pprint
sentence = "This is a common question."
char_count = {char: sentence.count(char) for char in sentence}
char_count_sorted = sorted(
    char_count.items(), key=lambda item:item[1], reverse=True)
pprint(char_count_sorted, width=1)

12. methods

  1. enumerate:对于dict,返回index和key。没有value
  2. items只针对dict。返回 key,value的tuple list
  3. dict相对与list好的一点,每个元素只出现一次。可用于计数。
  4. 匿名函数 在items的key中,是定于针对每一个成员的。另外parameter expression。和列表推导式相反。