Reputation: 10865
I am wondering how one can write a special Tally function, which treats the following list {{{1,0},{2,1,3}},{{1,1},{0,1,1}},{{2,1,2},{3,2}},{{1,0},{2,1}}}
as if:
{{1,0},{2,1,3}}
and {{1,1},{0,1,1}}
are equivalent, but not with {{1,0},{2,1}}
.{{1,0},{2,1,3}}
and {{2,1,2},{3,2}}
are equivalent.The elements of the level 1
list can be artitarily nested. How can I write such a function?
Many thanks.
Upvotes: 0
Views: 418
Reputation: 10695
Using SelectEquivalents
SelectEquivalents[list, Dimensions, #&, {#2[[1]], Length@#2}&]
which gives the same thing as Michael's answer, or
SelectEquivalents[list, Dimensions, #&, {#2[[1]] /. _Integer -> 0, Length@#2}&]
which gives Daniel's answer. Or, my personal favorite
SelectEquivalents[list, Dimensions, #&, {#1, Length@#2}&]
which gives
{{{2},3}, {{2,2}, 1}}
But, that reveals a flaw in using Dimension
, in that it does not know what to report when the sublists are of different dims, so if we replace Dimension
with Sort@Map[Length,#,{1,Infinity}]&
, we can begin to handle arbitrary dimensions. This gives
{{{2, 3}, 3}, {{2, 2}, 1}}
So, the dimensionality of each sublist is revealed. This does not sort below the first dimension, and I do not see how it can be immediately fixed.
Upvotes: 3
Reputation: 6520
Very similar to @Daniel's answer, but preserves a member of each class:
In[9]:= Tally[list, (Sort[Length /@ #] == Sort[Length /@ #2]) &]
Out[9]= {{{{1, 0}, {2, 1, 3}}, 3}, {{{1, 0}, {2, 1}}, 1}}
Upvotes: 4
Reputation: 6894
(1) Replace all integers with 0. (2) Sort at level one. This gives a unique representative for every class in the list.
ll2 = Map[Sort, ll /. aa_Integer -> 0]
Out[9]= {{{0, 0}, {0, 0, 0}}, {{0, 0}, {0, 0, 0}}, {{0, 0}, {0, 0, 0}}, {{0, 0}, {0, 0}}}
Tally[ll2]
Out[10]= {{{{0, 0}, {0, 0, 0}}, 3}, {{{0, 0}, {0, 0}}, 1}}
Daniel Lichtblau Wolfram Research
Upvotes: 7