在Mathematica中重新排列列表元素的更好方法

3
我想重新按照Tally[Characters["2723198931"]]中每个元素的第一个组件的顺序lst={"3", "1", "2", "9"}排序结果。也就是说,我希望输出结果为{{{"3", 2}}, {{"1", 2}}, {{"2", 2}}, {{"9", 2}}}。目前我有一种笨拙的解决方法,但想知道是否有人能提供简洁的解决方案。非常感谢。
3个回答

5

一种方法可能是

data = Tally[Characters["2723198931"]];
lst = {"3", "1", "2", "9"};

(*algorithm*)

pos =  Position[data[[All, 1]], #] & /@ lst;
Extract[data, pos]

输出

{{{"3", 2}}, {{"1", 2}}, {{"2", 2}}, {{"9", 2}}}

更新时间:凌晨2:37

上述截图中,我正在使用Windows 7系统的版本8.04。

在此输入图片描述


这就像我所做的一样,尽管我使用了 Select。有没有内置函数或更简单的方法?谢谢! - Qiang Li
这个对我来说不起作用。我需要 Position[data[[All, 1]], #][[1]]。在第8版中,它是否按原样工作? - Mr.Wizard
@Mr.Wizard,这段代码在我的 V 8.04 版本上按原样运行,请看截图! - Nasser

4

这应该会很快,但我没有测试过。在长列表上,您可以使用Dispatch[rls]来获得更好的性能。

key = {"3", "1", "2", "9"};
tal = Tally[Characters["2723198931"]];

rls = #[[1]] -> # & /@ tal;
key /. rls
{{"3", 2}, {"1", 2}, {"2", 2}, {"9", 2}}

另外还可以使用下面这个方法,对于长的计数列表速度会更快:

rls = Thread[tal[[All, 1]] -> tal];

2

或者,您可以做类似于以下方式的事情:

With[{tal = Tally[Characters["2723198931"]]},
  Flatten@Pick[tal, tal[[All, 1]], #] & /@ key] 

你是否经常需要计算字符串中的字符数?如果是这样,直接计算字符数可能比先将其转换为字符列表更有效率。例如:

str = StringJoin[RandomChoice[CharacterRange["0", "9"], 1000]];
key = {"3", "1", "2", "9"};

({#, StringCount[str, #]} & /@ key) // Timing

(* output: {0.000121, {{"3", 98}, {"1", 112}, {"2", 99}, {"9", 107}}} *)

With[{tal = Tally[Characters[str]]},
  Flatten@Pick[tal, tal[[All, 1]], #] & /@ key] // Timing 

(* output: {0.000567, {{"3", 98}, {"1", 112}, {"2", 99}, {"9", 107}}} *)

这些方法的问题在于你需要扫描每个key的列表。如果示例是实际使用的代表,那么这并不重要,但在更长的Tally集上,其效率非常低下。对于长度为5000的关键字/统计信息,key /. Dispatch@Thread[tal[[All, 1]] -> tal]速度快了330倍以上。由于这不比Pick更长,而且简单版本仍然更快,因此我更喜欢传播这种方法。如果只提供StringCount方法,我会投票支持它,因为它适用于该领域。 - Mr.Wizard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接