2011-12-21 46 views
3

我有一个内部列表可能具有可变长度的列表。我需要根据内部列表元素的字母顺序对外部列表进行排序。例如,给定的根据Mahtematica中的内部列表元素的字母顺序对列表进行排序

{{0, 0, 7}, {5, 0, 2, 3}, {0, 0, 10, 0}, {0, 6, 2}, {5, 1, 2}, {0, 3, 6, 1, 4}}

我想Sort后的输出列表是

{{0, 0, 10, 0}, {0, 0, 7}, {0, 3, 6, 1, 4}, {0, 6, 2}, {5, 0, 2, 3}, {5, 1, 2}}

我只是不知道如何处理内部列表的可变长度,以写一个比较函数。请帮忙。

编辑

BTW,原始列表是一个算一个。

编辑2

例如,我有一个列表:

{{0,0,7},{5,0,2,3},{0,0, 11,0},{0,0,1,12},{0,6,2},{5,1,2},{0,3,6,1,4}}

输出应该是:

{{0, 0,1,12},{0,0,11,0},{0,0,7},{0,3,6,1,4},{0,6,2},{5,0, 2,3},{5,1,2}}

的原因是,1是词法比11,其小于7以下。

+0

@ Mr.Wizard:我的编辑2是否解决您的问题? – 2011-12-21 20:52:28

+0

我想我终于明白了;谢谢。 – 2011-12-21 21:00:11

回答

6

您可以设置一个lexciographic comparator这样的:

lexComp[_, {}] := False; 
lexComp[{}, _] := True; 
lexComp[{a_, as___}, {b_, bs___}] := a < b || a == b && lexComp[{as}, {bs}]; 

然后,您可以排序使用来获得预期的效果:

Sort[{{0, 0, 7}, {5, 0, 2, 3}, {0, 0, 10, 0}, {0, 6, 2}, {5, 1, 2}, {0, 3, 6, 1, 4}}, lexComp] 

{{0, 0, 7}, {0, 0, 10, 0}, {0, 3, 6, 1, 4}, {0, 6, 2}, {5, 0, 2, 3}, {5, 1, 2}} 

如果你希望把这些数字作为字符串中的排序,你可以这样修改:

lessAsString[a_, b_] := Order @@ (ToString /@ {a, b}) === 1; 

olexComp[_, {}] := False; 
olexComp[{}, _] := True; 
olexComp[{a_, as___}, {b_, bs___}] := lessAsString[a, b] || a === b && olexComp[{as}, {bs}]; 

下面是这种排序的例子:

In[5]:= Sort[{{0, 0, 7}, {5, 0, 2, 3}, {0, 0, 11, 0}, {0, 0, 1, 12}, {0, 6, 2}, {5, 1, 2}, {0, 3, 6, 1, 4}}, olexComp] 

Out[5]= {{0, 0, 1, 12}, {0, 0, 11, 0}, {0, 0, 7}, {0, 3, 6, 1, 4}, {0, 6, 2}, {5, 0, 2, 3}, {5, 1, 2}} 
+0

不应该{0,0,10,0}在{0,0,7}之前? – 2011-12-21 20:17:08

+0

@QiangLi:如果你想把每个号码当作文本对待,那么是的。这是你的愿望吗? – 2011-12-21 20:20:36

+0

是的,把每个数字看作一个字符串 – 2011-12-21 20:21:26

1

这应该这样做

{{0, 0, 7}, {5, 0, 2, 3}, {0, 0, 10, 0}, {0, 6, 2}, {5, 1, 2}, {0, 3, 
    6, 1, 4}} // SortBy[#, ToString] & 

这工作,因为词汇,逗号和空格前面的数字,那么{A,B}是词汇之前{A,B,C}。

+0

我明白了。我最初正在考虑'排序',首先直接使用'ToString',在这种情况下是错误的,我需要'应用[StringJoin,Map [#,ToString]] ......我被卡住了。那么'SortBy'有没有被'Sort'共享? – 2011-12-21 20:07:12

+0

@Qiang Li - 'SortBy'可以让你对列表进行排序而不用改变它。作为替代方案,您可以在列表的每个元素上调用ToString,对结果字符串进行排序,然后在排序列表的每个元素上调用“ToExpression”来恢复整数的向量。这效率低得多。另一种方法是在列表的每个元素上调用“ToString”,然后在结果列表中调用“Ordering”,并使用“Take”将原始列表按排序顺序排列。我使用这个技巧很多来生成和缓存排列而不复制原始列表。 – cah 2011-12-21 20:09:43

+0

其实你的答案是错的!试试这个例子:{{0,0,7},{5,0,2,3},{0,0,11,0},{0,0,1,12},{0,6,2} },{5, 1,2},{0,3,6,1,4}}'。这里我期望{0,0,1,12}'在{0,0,11,0}之前' – 2011-12-21 20:12:45

2
alphaSort = #[[ Ordering @ Map[ToString, [email protected]#, {2}] ]] &; 

这是通过准备数据默认Ordering排序,然后使用顺序排序原始列表。

在这种情况下,填充所有列表的到相同的长度保持来自干扰此Sort属性:

排序通常订单表达式通过将较短的第一,然后比较部件以深度优先的方式。

ToString用于获取字母顺序而不是数字。

+0

我明白你的观点。是的,它似乎工作。 – 2011-12-21 21:15:47

+1

这里它去。谢谢! :) – 2011-12-21 21:41:41

相关问题