如@High Performance Mark和@Nicholas Wilson所说,我会建议通过Transpose
或Thread
将这两个列表合并。在这种情况下,
In[1]:= Transpose[{clusterIndices, points}]==Thread[{clusterIndices, points}]
Out[1]:= True
有一次,我比较了一下哪个更快,我认为 Thread
稍微快一些。但是,只有在使用非常长的列表时才真正重要。
@High Performance Mark 提出了使用 Select
的好建议。但是,它只允许您一次提取一个聚类。选择聚类1的代码如下:
Select[Transpose[{clusterIndices, points}],
既然您似乎想要生成所有的集群,我建议按照以下步骤进行:
GatherBy[Transpose[{clusterIndices, points}],
这个方法的优点是只有一行代码,唯一棘手的部分在于选择正确的结果列表Part
。确定需要多少个All
项的技巧在于注意到:
Transpose[{clusterIndices, points}][[All,2]]
需要从转置列表中取回点数,因此需要使用第二个All
来处理“聚类”列表中的一个额外级别。
值得注意的是,GatherBy
中的第二个参数是一个接受一个参数的函数,可以与任何您希望使用的函数交换。因此,它非常有用。但是,如果您想在收集数据时对其进行转换,我建议您查看Reap
和Sow
。
编辑:Reap
和Sow
有些被低估,但功能强大。它们有些令人困惑,但我怀疑GatherBy
在内部使用它们实现。例如,
Reap[ Sow[#[[2]], #[[1]] ]& /@ Transpose[{clusterIndices, points}], _, #2& ]
这段代码与我之前的代码做的事情相同,但不需要将索引从点中删除。基本上,Sow
会为每个点标记其索引,然后Reap
收集所有标记(第二个参数使用_
),并仅输出点。个人而言,我使用这个方法替代了GatherBy
,并将其编码为一个函数进行加载,如下所示:
SelectEquivalents[x_List,f_:Identity, g_:Identity, h_:(#2&)]:=
Reap[Sow[g[#],{f[#]}]&/@x, _, h][[2]];
注意:这段代码是对5.x帮助文件中内容的修改。但是,6.0和7.0版本的帮助文件删除了很多有用的示例之一,其中就包括这个示例。
Reap
和Sow
的另一个优点是,你可以sow
多个标签,即如果你的数据适合多个类别,你可以将数据分组。为此,请在SelectEquivalents
中删除f
周围的花括号,并让f
返回数据所属的标签列表。 - rcollyer