不使用 for 循环转置列表列表我希望有一种方法可以在不使用 for 循环的情况下转置列表列表。 也就是说,一些函数(例如,将其称为“Listtranspose”)翻转列表列表的“行”和“列”,如下所示:
listlist = {{"cat", "dog", "mouse"}, {"meow", "bark", "squeak"}};
tranlist = Listtranspose(listlist);
Show(tranlist);
/*Result:
{{"cat", "meow"}, {"dog", "bark"}, {"mouse", "squeak}}
替代实现可能是这样的:
listlist = {{"cat", "dog", "mouse"}, {"meow", "bark", "squeak"}};
nr = NItems(listlist);
col1 = listlist[1::nr][1];
col2 = listlist[1::nr][2];
col3 = listlist[1::nr][3];
translist = EvalList({col1, col2, col3});
我更喜欢后一种实现,因为我可能只需要转置“列”的一个子集,而不是整个列表。
当然,这可以使用 For 循环来完成,但要求这样做的原因是 For 循环可能很慢。 我处理大块文本,我相信这会大大加快我的速度。
归功于@vince_faller最初问这个。不使用 for 循环转置列表列表
脚本回复:不使用 for 循环转置列表列表再考虑一下这个。我仍然无法击败 for 循环,但我想我会把它写下来以防它对任何人有帮助。
// make a blank data table with the right shape
dt = As Table(J(nr, nc, .), <<PRIVATE></PRIVATE>
回复:不使用 for 循环转置列表列表@Craige_Hales感谢克雷格的深刻见解。 我同意,我对 for 循环与并行分配方法进行了速度测试,并行分配的速度要慢得多。 我的列表数组是 718r x 14182c,所以超过 1000 万个元素。 我运行脚本约 10 分钟,但操作没有完成。 这似乎比您上面预测的数据慢一点,但要考虑的变量太多(例如计算机系统、列与行的比率?)。 对于同一张表,for 循环在 ~10.1s 时要快得多。
仍然比我想要的要慢。 如果有一个可以在内部执行此操作的 JMP 函数,那就太好了。
回复:不使用 for 循环转置列表列表但是,经过一些测试,我认为简单的嵌套循环比任何其他基于 JSL 的方法都要快。
result = {};
for( c = 1, c <= nc, c += 1,
thisrow = {}; // build a row from a column
for( r = 1, r <= nr, r += 1,
thisrow[r] = testList[r][c];
);
result[c] = thisrow;
);@DonMcCormack - 挑战!
The blue-line for-loop is consistently better. The purple JSON-table might overtake it, but I'm running out of memory. The parallel-assign trick begins to fail for large numbers.蓝线 for 循环始终更好。 紫色的 JSON 表可能会超过它,但我的内存不足。 并行分配技巧开始对大数失效。
并行分配可能一直在阻塞线程。 它首先击败了 json 数据表,因为两者之间的开销不同。
回复:不使用 for 循环转置列表列表是的,如果有更多的列表操作函数就好了。 我想不出一个好的或快速的方法,但玩了一会儿之后想出了这个。 它需要 JMP 15,在 14 中失败。
list = {{"lion", "tiger", "puma"}, {"lamp", "torch", "pharos"}, {"lark", "toucan", "pigeon"}, {"lawn", "terrace", "patio"}};
jlist = As JSON Expr( list );
dt1 = JSON To Data Table( jlist, invisible(1) );
dt1 << New Column( "row", numeric, setvalues( 1 + Floor( (0 :: (N Rows( dt1 ) - 1)) / N Items( list[1] ) ) ) );
dt2 = dt1 << Split( Split By( :row ), Split( column(dt1,1) ), Sort by Column Property, invisible(1) );
Close( dt1, nosave );
transposed = dt2[0, 0];
Close( dt2, nosave );
Show( list, transposed );list = {{"lion", "tiger", "puma"}, {"lamp", "torch", "pharos"}, {"lark", "toucan", "pigeon"}, {"lawn", “露台”,“天井”}};
转置= {{“狮子”,“灯”,“百灵”,“草坪”},{“老虎”,“火炬”,“巨嘴鸟”,“露台”},{“美洲狮”,“灯塔", "鸽子", "天井"}};
取消隐藏中间表以查看它在做什么。 真正的解决方案应该处理长度不等的行。
回复:不使用 for 循环转置列表列表@Craige_Hales写了一个很好的解释,我经常使用。使用 Parallel Assign 进行多线程故障排除
回复:不使用 for 循环转置列表列表@vince_faller
头脑==吹。
以前从未听说过 Parallel Assign 功能。 我试过了,是的,它有效。 尽管我正在处理字符串并且这在技术上是一个矩阵函数,但它并不关心。 尝试一下它会很有趣,看看它是否比 for 循环更快。 一旦我知道,将尝试在这里更新。
谢谢你的主意!
回复:不使用 for 循环转置列表列表我发誓我看到有人做了类似的事情
{"cat", "dog", "mouse", "meow", "bark", "squeak"}[[1 1, 1 1]]
// and had it return
{{"cat", "cat"}, {"cat", "cat"}}
在 discovery 的一次演讲中,但我一直无法重现它。难道一切都是梦?
如果我没记错的话,他们以某种方式从一个平面列表中形成了一个新列表,就像那样。我可能记错了。
话虽如此,您可能可以非常快地进行并行分配
names default to here(1);
listlist = {{"cat", "dog", "mouse"}, {"meow", "bark", "squeak"}};
m = J(nc, nr, -1);
::trans_list = Aslist(m);
Parallel Assign({l = listlist},
m[a, b] = (
::trans_list[a][b] = l[b][a];
)
);
show(::trans_list);