我正在使用Python 2.7并具有以下功能:
pipe
我想创建一个一维列表,其中元素按子列表中的位置顺序排列,然后按子列表的顺序排列。因此,上述列表的正确输出是:
my_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
这是我的(不正确的)尝试:
[1, 4, 7, 2, 5, 8, 3, 6, 9]
这使我的2维列表变平,并且给了我:
def reorder_and_flatten(my_list):
my_list = [item for sublist in my_list for item in sublist]
result_nums = []
for i in range(len(my_list)):
result_nums.extend(my_list[i::3])
return result_nums
result = reorder_and_flatten(my_list)
此列表的前半部分正确,但后半部分不正确。
我也希望我的函数只能处理2个子列表。例如,如果给出:
[1, 4, 7, 2, 5, 8, 3, 6, 9, 4, 7, 5, 8, 6, 9, 7, 8, 9]
正确的输出是:
[[1, 2, 3], [], [7, 8, 9]
有什么想法吗?
谢谢!
答案 0 :(得分:2)
您要先进行拼合然后重新排序,这比重新排序然后进行拼合要困难得多。
首先,对于您的第一个问题,就是“解压缩”,如zip
的文档中所述:
>>> my_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list(zip(*my_list))
... [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
(在Python 2.7中,您可以在此处编写zip(…)
而不是list(zip(…))
,但是这样,同一示例在2.x和3.x中的工作原理相同。)
然后,您已经知道如何扁平化:
>>> [item for sublist in zip(*my_list) for item in sublist]
[1, 4, 7, 2, 5, 8, 3, 6, 9]
但是对于第二种情况,情况变得有些复杂,其中某些列表可能为空(或可能更短?)。
没有类似于zip
的函数,但是会跳过缺少的值。您可以轻松编写一个。但是相反,有一个 函数,它类似于zip
,但用None
(或您喜欢的其他任何东西)izip_longest
填充缺失值。因此,我们可以使用它,然后在展平时过滤掉None
值:
>>> my_list = [[1, 2, 3], [], [7, 8, 9]]
>>> from itertools import izip_longest
>>> list(izip_longest(*my_list))
[(1, None, 7), (2, None, 8), (3, None, 9)]
>>> [item for sublist in izip_longest(*my_list) for item in sublist if item is not None]
[1, 7, 2, 8, 3, 9]
(在Python 3中,函数izip_longest
重命名为zip_longest
。)
值得注意的是,ShadowRanger's answer涵盖的roundrobin
食谱是解决此问题的更好方法,甚至更易于使用(只需从文档中复制并粘贴,或{ {1}},然后从那里使用它)。 很难理解-但是值得花些时间来理解它(并在遇到问题时寻求帮助)。
答案 1 :(得分:1)
<div *ngFor="let item of myFormArray.controls; let i=index">
<div formGroupName="{{i}}">
<input formControlName="myFormGroupSubControl1" />
<input formControlName="myFormGroupSubControl2" />
即
result = [l[i] for i in range(max(len(v) for v in my_list)) for l in my_list if l]
答案 2 :(得分:1)
The itertools
module's recipes section提供了insert into [Fleet].[dbo].[AccountsReports]
([AccountId],
[ReportId],
[ReportName])
SELECT
@account AccountId
,[ReportId]
,[Name]
FROM [Fleet].[dbo].[Reports] t1
where ReportId in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,54) and
not exists (
SELECT
1
FROM [Fleet].[dbo].[Reports] t2
WHERE t1.ReportId = t2.ReportId and t1.Name = t2.Name
)
的食谱,可以完全满足您的需求。它会产生一个生成器,但是您的预期行为将显示为:
roundrobin
您的原始代码的主要问题是它遍历# define roundrobin recipe here
from itertools import cycle, islice
def roundrobin(*iterables):
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
# Recipe credited to George Sakkis
pending = len(iterables)
nexts = cycle(iter(it).next for it in iterables)
while pending:
try:
for next in nexts:
yield next()
except StopIteration:
pending -= 1
nexts = cycle(islice(nexts, pending))
def reorder_and_flatten(my_list):
return list(roundrobin(*my_list))
,并以for i in range(len(my_list)):
扩展。问题是,这最终会从索引3开始复制元素(索引3已被选择为索引0切片的第二个元素)。这里还有很多其他小的逻辑错误,因此重用配方要容易得多。
这将是相当有效的,并且比大多数手动解决方案具有更好的通用性(即使子列表的长度不均匀,它也可以正确轮转,并且不需要二次通过过滤或任何形式的特殊处理即可my_list[i::3]
就像None
一样)。
答案 3 :(得分:1)
如果您愿意使用第三方库,则可以使用NumPy和np.ndarray.ravel
:
import numpy as np
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
res_a = A.ravel('F') # array([1, 4, 7, 2, 5, 8, 3, 6, 9])
对于有一个或多个空列表的情况,可以使用filter
删除空列表:
B = np.array(list(filter(None, [[1, 2, 3], [], [7, 8, 9]])))
res_b = B.ravel('F') # array([1, 7, 2, 8, 3, 9])
两个解决方案都要求非空子列表包含相同数量的项目。如果必须进行列表转换,则可以使用res_a.tolist()
。
尽管这些“黑匣子”方法不会给您带来太多帮助,但对于大型数组,它们比基于list
的操作要快。另请参见What are the advantages of NumPy over regular Python lists?