Python中如何遍历二维列表并生成新的列表?

原始数据是个二维 list,list 的长度不定,里面的每个子项长度也不定,类似下面这样情况:
original_list = [[‘a’,‘b’,‘c’],[’@’,’#’,’$’,’%’],[‘1’,‘2’],…]
现在需要把所有的子项遍历一遍(每个子项取一个值生成一个新的 list,把所有的情况都排列组合出来),得到类似这样的结果:
target_list = [[‘a’,’@’,‘1’,…],[‘a’,’@’,‘2’,…],[‘a’,’#’,‘1’,…],[‘a’,’#’,‘2’,…],…]

请问如何优雅的实现?
Python中如何遍历二维列表并生成新的列表?


18 回复

itertools.product ?


# 假设你有一个二维列表,想对每个元素进行处理后生成新列表
original_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# 方法1:列表推导式(最Pythonic的方式)
new_list = [[item * 2 for item in row] for row in original_list]
print(new_list)  # 输出:[[2, 4, 6], [8, 10, 12], [14, 16, 18]]

# 方法2:嵌套循环
new_list2 = []
for row in original_list:
    new_row = []
    for item in row:
        new_row.append(item * 2)
    new_list2.append(new_row)
print(new_list2)  # 输出同上

# 方法3:使用map函数
new_list3 = [list(map(lambda x: x * 2, row)) for row in original_list]
print(new_list3)  # 输出同上

# 如果你只是想展平二维列表(变成一维)
flattened = [item for row in original_list for item in row]
print(flattened)  # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9]

# 或者用itertools.chain
from itertools import chain
flattened2 = list(chain(*original_list))
print(flattened2)  # 输出同上

核心就是列表推导式,一行搞定遍历和转换。

哈哈哈哈莫名喜感

这个生成笛卡尔积元祖的方法是没错,但是我运行了一遍得到的结果貌似有问题?

original = [[‘a’,‘b’,‘c’],[’’,’#’,’$’,’%’],[‘1’,‘2’]]
for i in product(x for x in original):
print(i)
------得到的结果-----
([‘a’, ‘b’, ‘c’],)
([’’, ‘#’, ‘$’, ‘%’],)
([‘1’, ‘2’],)

>>> from itertools import product
>>> o = [[‘a’,‘b’,‘c’],[’@’,’#’,’$’,’%’],[‘1’,‘2’]]
>>> for m, n, f in product(o[0],o[1],o[2]):
… t.append([m,n,f])

哪里好笑了?
那是因为你没仔细看 product 怎么用

最简单的办法可能是这样:itertools.product(*original)
不保证有没有问题……毕竟不太常写 python

这样写运行没问题,但是如果不知道原始 list 有多少子项,就没法这样操作
itertools.product(*original) 这样写没问题

谢谢各位 :)

先从最外层取两个,再最内层取一个,可以用下标
itertools.combinations

最先想到的是深搜。。

总感觉用 *展开其实有点 trick 并且不是很安全(可能 list 很大?)

有没有大佬分析一下?

分治?

表示不是很会 python

伪代码大概这个意思。。
dfs(outer_list, current_result, ans)
if outer_list == null
ans.push_back(current_result)
return
end
// loop over inner_list
for item in *outer_list
current_result.push_back(item)
dfs(outer_list.next(), current_result, and)
current_result.pop_back()
end
end

排版醉了

看了 itertools.product 的源代码,直接这样就能实现了:

original = [[‘a’,‘b’,‘c’],[’@’,’#’,’$’,’%’],[‘1’,‘2’]]
target = [[]]
for pool in original:
…target = [x+[y] for x in target for y in pool]

>>> from itertools import product
>>> original = [[‘a’,‘b’,‘c’],[’@’,’#’,’$’,’%’],[‘1’,‘2’]]
>>> list(product(*original))
[(‘a’, ‘@’, ‘1’), (‘a’, ‘@’, ‘2’), (‘a’, ‘#’, ‘1’), (‘a’, ‘#’, ‘2’), (‘a’, ‘$’, ‘1’), (‘a’, ‘$’, ‘2’), (‘a’, ‘%’, ‘1’), (‘a’, ‘%’, ‘2’), (‘b’, ‘@’, ‘1’), (‘b’, ‘@’, ‘2’), (‘b’, ‘#’, ‘1’), (‘b’, ‘#’, ‘2’), (‘b’, ‘$’, ‘1’), (‘b’, ‘$’, ‘2’), (‘b’, ‘%’, ‘1’), (‘b’, ‘%’, ‘2’), (‘c’, ‘@’, ‘1’), (‘c’, ‘@’, ‘2’), (‘c’, ‘#’, ‘1’), (‘c’, ‘#’, ‘2’), (‘c’, ‘$’, ‘1’), (‘c’, ‘$’, ‘2’), (‘c’, ‘%’, ‘1’), (‘c’, ‘%’, ‘2’)]

如果 original 中的 list 元素量大,product 是个生成器,要用 for 去调用,不然内存爆菊。

用深搜写的……
original_list = [[‘a’,‘b’,‘c’],[’@’,’#’,’$’,’%’],[‘1’,‘2’],[‘1’,‘2’,‘8’]]
target_list = []
def dfs(n,i,str0):
str1 = []
for j in range(len(str0)):
str1.append(str0[j])
str1.append(original_list[n][i])
if(n == len(original_list) - 1):
target_list.append(str1)
else:
for j in range(len(original_list[n+1])):
dfs(n+1,j,str1)
for j in range(len(original_list[0])):
dfs(0,j,[])
print(target_list)

lst = [[‘a’, ‘b’, ‘c’], [’@’, ‘#’, ‘$’, ‘%’], [‘1’, ‘2’]]

1.
import itertools
[list(i) for i in itertools.product(*lst)]

2.
def cross(lst):
def swim(l, t, res):
if len(l) == 0:
res += [t]
return
for i in l[0]:
swim(l[1:], t + [i], res)

res = []
swim(lst, [], res)
return res

从微博过来的,贴个 js 实现吧,不过 python 应该更简单,因为 python 里面的有些方法工具感觉更强大
function map(arr) {
return arr.reduce((previous, current) => {
var mapped = []
previous.map(val1 => {
current.map(val2 => {
return Array.isArray(val1) ? mapped.push([…val1, val2]) : mapped.push([val1, val2])
})
})
return mapped
})
}

回到顶部