1
$\begingroup$

I have following list

list = 
  {{{1 -> 3, 2 -> 1, 3 -> 2}, {1 -> 6, 2 -> 7}, {1 -> 5}}, 
  {{1 -> 7, 2 -> 8, 3 -> 6, 4 -> 9, 5 -> 3}, {1 -> 1, 2 -> 5, 3 -> 3, 4 -> 2}, 
   {1 -> 6}}, 
  {{1 -> 2, 2 -> 4}, {1 -> 4}, {1 -> 3, 2 -> 5, 3 -> 3}}}

I evaluated

list1 = Values[list]  

and got

{{{3, 1, 2}, {6, 7}, {5}}, 
 {{7, 8, 6, 9, 3}, {1, 5, 3, 2}, {6}}, 
 {{2,4}, {4}, {3, 5, 3}}}    

Now I want to sort all the elements from each innermost sublist from higher to lower values and and take ratios from 2nd element onward of each sublist with the first element. When a sublist has only one element then the ratio will be zero.

I am trying for two days but still unable to do it. Please help me.

$\endgroup$
  • 1
    $\begingroup$ Can you how the expected output for your example? $\endgroup$ – bill s Nov 21 '17 at 20:41
1
$\begingroup$

Consider list1 to be the output obtained from evaluating Values[list], as displayed in the question.

After evaluating

Apply[
  Through[{First, Rest}[Reverse[Sort[{##}]]]] &,
  list1, {2}] 

we obtain

{
  {{3, {2, 1}}, {7, {6}}, {5, {}}}, 
  {{9, {8, 7, 6, 3}}, {5, {3, 2, 1}}, {6, {}}}, 
  {{4, {2}}, {4, {}}, {5, {3, 3}}}
 }

Apply allows us to apply a function on every sub-list in list1 ie the output of Apply[f[{##}]&,list1,{2}] is:

{
  {f[{3, 1, 2}], f[{6, 7}], f[{5}]}, 
  {f[{7, 8, 6, 9, 3}], f[{1, 5, 3, 2}], f[{6}]}, 
  {f[{2, 4}], f[{4}], f[{3, 5, 3}]}
 }

Instead of applying a generic function like f[{##}]& we need to Sort the entries of each list and separate the first item from the rest of the list. This is achieved with substituting

Through[{First, Rest}[Reverse[Sort[{##}]]]] &

for our generic f.

Note how, this function first Sorts the entries of each list in ascending order (default), then it Reverses the output of Sort (in order to get the descending sort that is required).

Finally we use Through to obtain a list of {First[#],Rest[#]}& items of each sub-list.

As an aside, consider the effect of the preceding function on the first sub-list ie evaluate {First[#],Rest[#]}&@{3, 1, 2}. The output is, as required, {3,{1,2}}.

The pairs of properly sorted and separated sub-lists can now be manipulated to produce the required ratios (see question) by applying the following rules

{{n_, {}} -> {0}, {n_, l_} :> l/n}

The first rule will take care of every sub-list with a single entry, while the second rule will produce the required ratios, without risking division-by-{} unwanted output, since that danger is removed by the application of the first rule.


The notebook code along with the output is given below

Apply[
  Through[{First, Rest}[Reverse[Sort[{##}]]]] &,
  list1, {2}] /.{
 {n_, {}} -> {0}, 
 {n_, l_} :> l/n
}

The output of evaluating the code above is

{
  {{2/3, 1/3}, {6/7}, {0}}, 
  {{8/9, 7/9, 2/3, 1/3}, {3/5, 2/5, 1/5}, {0}}, 
  {{1/2}, {0}, {3/5, 3/5}}
 }
$\endgroup$
  • $\begingroup$ Awesome. Thank you for giving all the explanation with the solution. This is my answer. Thank you so much. $\endgroup$ – nirmal Nov 22 '17 at 19:42
0
$\begingroup$

Not sure how many elements you want in your final array, but try this.

list = {{{1 -> 3, 2 -> 1, 3 -> 2}, {1 -> 6, 
    2 -> 7}, {1 -> 5}}, {{1 -> 7, 2 -> 8, 3 -> 6, 4 -> 9, 
    5 -> 3}, {1 -> 1, 2 -> 5, 3 -> 3, 4 -> 2}, {1 -> 6}}, {{1 -> 2, 
    2 -> 4}, {1 -> 4}, {1 -> 3, 2 -> 5, 3 -> 3}}};

list1 = Values[list];

First the sort.

list2 = list1
list3 = list1

For[i = 1, i <= Length[list1], i++, 
 For[j = 1, j <= Length[list1[[i]]], j++, 
  list2[[i, j]] = SortBy[list1[[i, j]], -N[#] &]]]

Now the sublists are sorted in list2.

list2
    (* {{{3,2,1},{7,6},{5}},{{9,8,7,6,3},{5,3,2,1},{6}},{{4,2}{4},{5,3,3}}} *)

Get the ratios.

For[i = 1, i <= Length[list1], i++,
 For[j = 1, j <= Length[list1[[i]]], j++,
  For[k = 1, k <= Length[list2[[i, j]]], k++,
   If[Length[list2[[i, j]]] == 1, list3[[i, j, k]] = 0,
    list3[[i, j, k]] = list2[[i, j, k]]/list2[[i, j, 1]]
    ]]]]

Final array in list3

(* {{{1,2/3,1/3},{1,6/7},{0}},{{1,8/9,7/9,2/3,1/3},{1,3/5,2/5,1/5},{0}},{{1,1/2},{0},{1,3/5,3/5}}} *)
$\endgroup$
  • $\begingroup$ Wow, thank you so much for the help. your help is appreciated. $\endgroup$ – nirmal Nov 22 '17 at 19:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.