如何将列表切成不同长度的子列表
Posted
技术标签:
【中文标题】如何将列表切成不同长度的子列表【英文标题】:How to slice a list into sublists with different length 【发布时间】:2022-01-18 13:12:57 【问题描述】:上下文:我想制作多词搜索网格
我有一个这样的文本行输入(包含数字和字母字符串):
2 <--- tells how many grids/boxes
3 <--- tells rows/length
4 <--- tells columns/width
catt <--\
aata <--- letters that will fill the box
tatc <--/
cat <--- the word that will be search inside the box
5 <--- and repeat but start with the rows
5
gogog
ooooo
godog
ooooo
gogog
dog
所有这些都在一个列表中作为输入
但是,我需要在里面传递变量。所以我假设我需要将列表拆分/切片为另一个列表,其中包含我需要的所有变量。
我想我需要像这样拆分 cat
和 dog
的变量:
#variables for cat and dog
rows, cols = [3, 5], [4, 5] #the numbers have to be integer
matrix = [['catt', 'aata', 'tatc'], ['gogog', 'ooooo', 'godog', 'ooooo', 'gogog']]
word = ['cat', 'dog']
这些是我需要的变量。但我不知道如何从上面的输入中拆分它。
如果有任何不同的方式,请随时解释。谢谢
【问题讨论】:
"cattaatatatc" 有一瞬间我以为这是 DNA。但后来一只狗出现了。 【参考方案1】:我已将您的输入保存在一个名为“input.txt”的文件中,并使用了以下方法:
with open("input.txt", "r") as f:
lines = [x.strip() for x in f.readlines()]
n_animals, other_lines = int(lines[0]), lines[1:]
rows, cols, matrix, word = [[] for _ in range(4)] # comment by @Stef - well spotted
while len(other_lines) > 0:
rows.append(int(other_lines[0]))
cols.append(int(other_lines[1]))
matrix.append(list(map(lambda x: x[:cols[-1]], other_lines[2:2 + rows[-1]])))
word.append(other_lines[2 + rows[-1]])
other_lines = other_lines[2 + rows[-1] + 1:]
if len(matrix) == n_animals:
pass # Do we need to take any action here? like break?
print(rows)
print(cols)
print(matrix)
print(word)
输出
[3, 5]
[4, 5]
[['catt', 'aata', 'tatc'], ['gogog', 'ooooo', 'godog', 'ooooo', 'gogog']]
['cat', 'dog']
我的假设是你想用那个 width 变量做点什么,因此我把每个单词都剪成了cols[-1]
个字符。现在,你需要决定如果len(matrix) > n_animals
怎么办。
跟进
结合一些反馈以提高效率:
i = 0
while i < len(other_lines):
rows.append(int(other_lines[i]))
cols.append(int(other_lines[i + 1]))
matrix.append(list(map(lambda x: x[:cols[-1]], other_lines[i + 2 : i + 2 + rows[-1]])))
word.append(other_lines[i + 2 + rows[-1]])
i += 2 + rows[-1] + 1
if len(matrix) == n_animals:
pass # Do we need to take any action here? like break?
【讨论】:
rows, cols, matrix, word = [[]] * 4
你确定吗?你不想要rows, cols, matrix, word = [[] for _ in range(4)]
吗?否则它是相同空列表的四倍,当您开始修改其中一个空列表时,会发生奇怪的事情。
@Stef 很好看。我被带走了,因为我有rows, cols, matrix, word = [], [], [], []
,但建议的方式是错误的。我会采纳你的意见。 +1
还有other_lines = other_lines[2 + rows[-1] + 1:]
在while循环中其实代价很大;在 while 循环的每次迭代中,您都在复制所有剩余的行;所以总复杂度是二次的而不是线性的。为了规避这个问题,您可以使用索引i
,写作rows.append(int(other_lines[i]))
,而不是重复地对列表进行切片;或者您可以使用带有next
的迭代器而不是列表。
另外,主循环的停止条件应该基于n_animals
!
@Stef 好吧,我不知道用例来得出结论。如果我到达n_animals
,我应该停下来还是应该做其他事情——以防指定的动物数量超过预期?什么是预期 3 只动物而只指定 2 只?还因为 - 在指定的示例中 - n_animals
无论如何都是一个冗余变量。【参考方案2】:
使用next
遍历文件对象:
with open('input.txt') as f:
n_animal = int(next(f).strip())
rows, cols, matrices, words = [], [], [], []
for _ in range(n_animals):
n_row = int(next(f).strip())
n_col = int(next(f).strip())
rows.append(n_row)
cols.append(n_col)
matrix = [list(next(f).strip()) for _ in range(n_row)]
matrices.append(matrix)
words.append(next(f).strip())
print('rows, cols = ', rows, cols)
print('matrices = ', matrices)
print('words = ', words)
# rows, cols = [3, 5] [4, 5]
# matrices = [[['c', 'a', 't', 't'], ['a', 'a', 't', 'a'], ['t', 'a', 't', 'c']], [['g', 'o', 'g', 'o', 'g'], ['o', 'o', 'o', 'o', 'o'], ['g', 'o', 'd', 'o', 'g'], ['o', 'o', 'o', 'o', 'o'], ['g', 'o', 'g', 'o', 'g']]]
# words = ['cat', 'dog']
注意:如果可以使用字符串列表而不是列表列表,则可以替换 matrix =
行:
# list of lists
matrix = [list(next(f).strip()) for _ in range(n_row)]
# list of strings
matrix = [next(f).strip() for _ in range(n_row)]
如果您的输入已经存储为字符串列表,而不是要读取的文件,您仍然可以在迭代器上使用 next
:
lines = ['2', '3', '4', 'catt', ...]
f = iter(lines)
n_animal = int(next(f).strip())
rows, cols, matrices, words = [], [], [], []
for _ in range(n_animals):
n_row = int(next(f).strip())
n_col = int(next(f).strip())
rows.append(n_row)
cols.append(n_col)
matrix = [list(next(f).strip()) for _ in range(n_row)]
matrices.append(matrix)
words.append(next(f).strip())
【讨论】:
好的答案顺便说一句,但是如果我想让matrices
像这样 [['catt', 'aata', 'tatc'], ['gogog', 'ooooo', 'godog', 'ooooo', 'gogog']]
怎么办。我试过 splitlines()
但输出是这样的 [[['catt'], ['aata'], ['tatc']], [['gogog'], ['ooooo'], ['godog'], ['ooooo'], ['gogog']]]
。也许你可以帮忙:)
@GilangArindawa 我不知道你所说的“我试过 splitlines()”是什么意思。我没有得到和你一样的结果。您是否尝试使用 matrix = [next(f).strip() for _ in range(n_row)]
而不是 matrix = [list(next(f).strip()) for _ in range(n_row)]
?
哇,这很明显,我没想到,哈哈。谢谢! :D【参考方案3】:
如果每行信息的位置始终是“固定的”,那么最简单的选择是将行转换为列表,然后具体引用每一行。比如:
data = text.splitlines()
grids = data[0]
rows = data[1]
cols = data[2]
letters = data[3:7]
repeat = data[7:9]
remain = data[9:]
print(grids, rows, cols, letters, repeat, remain)
【讨论】:
它不是固定的。重复的次数由写入data[0]
的整数给出。然后在 data[i+1] 处给出字母的行数,其中 i 是您重复的次数。以上是关于如何将列表切成不同长度的子列表的主要内容,如果未能解决你的问题,请参考以下文章