Sort lists according to the order of another - Mathematica Stack Exchange most recent 30 from mathematica.stackexchange.com 2019-10-19T19:13:46Z https://mathematica.stackexchange.com/feeds/question/7679 https://creativecommons.org/licenses/by-sa/4.0/rdf https://mathematica.stackexchange.com/q/7679 37 Sort lists according to the order of another Tyson Williams https://mathematica.stackexchange.com/users/738 2012-06-29T20:17:05Z 2018-05-26T11:18:21Z <p>I have three parallel lists (i.e. the elements in position i of each list are related). I want to sort the first list using the function <code>Sort</code> and make the same changes to the other lists so that I still have parallel lists when finished.</p> <p>How can I do this?</p> <p>As an example: Given the lists <code>{2, 3, 1}</code>, <code>{a, b, c}</code>, and <code>{alpha, beta, gamma}</code>, sorting all lists according the first one gives <code>{1, 2, 3}</code>, <code>{c, a, b}</code>, and <code>{gamma, alpha, beta}</code>.</p> https://mathematica.stackexchange.com/questions/7679/-/7680#7680 34 Answer by kglr for Sort lists according to the order of another kglr https://mathematica.stackexchange.com/users/125 2012-06-29T20:22:48Z 2012-06-30T08:50:30Z <p>You can use combination of <code>Part</code> and <code>Ordering</code> as</p> <pre><code>list1[[ Ordering @ list2 ]] </code></pre> <p>to sort <code>list1</code> in the order of <code>list2</code>.</p> <p>Examples:</p> <pre><code>{list1, list2, list3} = {{1, 3, 2}, {a, b, c}, {x, y, z}}; list2[[ Ordering @ list1 ]] </code></pre> <p>gives</p> <pre><code>{a, c, b} </code></pre> <p>and</p> <pre><code>list3[[ Ordering @ list1 ]] </code></pre> <p>gives</p> <pre><code>{x, z, y} </code></pre> <p>EDIT: Using with lists of lists, to sort the entire array based on the first list:</p> <pre><code>list = {list1, list2, list3}; list[[ All, Ordering @ list[] ]] </code></pre> <p>gives</p> <pre><code>{{1, 2, 3}, {a, c, b}, {x, z, y}} </code></pre> <p>But ... as I just noticed, this is already covered in @Mr.Wizard's answer long before my edit.</p> https://mathematica.stackexchange.com/questions/7679/-/7681#7681 28 Answer by Rojo for Sort lists according to the order of another Rojo https://mathematica.stackexchange.com/users/109 2012-06-29T20:32:07Z 2012-06-29T20:37:50Z <pre><code>lists = {list1, list2, list3} = {{1, 3, 2}, {a, b, c}, {x, y, z}}; </code></pre> <p>Another option</p> <pre><code>SortBy[lists\[Transpose], First]\[Transpose] </code></pre> <blockquote> <p>{{1, 2, 3}, {a, c, b}, {x, z, y}}</p> </blockquote> https://mathematica.stackexchange.com/questions/7679/-/7687#7687 23 Answer by Mr.Wizard for Sort lists according to the order of another Mr.Wizard https://mathematica.stackexchange.com/users/121 2012-06-29T23:45:19Z 2012-06-29T23:45:19Z <p><code>Ordering</code> and <code>Part</code> is more efficient than <code>SortBy</code> and <code>Transpose</code> and it can also be done in one pass as I will demonstrate.</p> <p>I create three lists of different type as described in the question:</p> <pre><code>a = RandomInteger[999, 500]; b = RandomReal[1, 500]; c = CharacterRange["a", "z"] ~RandomChoice~ 500; </code></pre> <p>I use the <a href="https://stackoverflow.com/a/4199042/618728"><code>timeAvg</code></a> function for testing:</p> <pre><code>SortBy[{a, b, c}\[Transpose], First]\[Transpose] // timeAvg {a, b, c}[[All, Ordering@a]] // timeAvg </code></pre> <blockquote> <p>0.00027456</p> <p>0.000026944</p> </blockquote> <p>As can be seen second method is more than an order of magnitude faster on this data.</p> <p>It is noteworthy that these two forms as shown <em>do not</em> perform the same operation because <code>SortBy[list, func]</code> is not a stable sort. Observe:</p> <pre><code>lists = {{8, 8, 6, 3, 7}, {"i", "e", "f", "b", "m"}, {"q", "x", "u", "w", "z"}}; SortBy[lists\[Transpose], First]\[Transpose] lists[[All, Ordering @ First @ lists]] </code></pre> <blockquote> <pre><code>{{3, 6, 7, 8, 8}, {"b", "f", "m", "e", "i"}, {"w", "u", "z", "x", "q"}} {{3, 6, 7, 8, 8}, {"b", "f", "m", "i", "e"}, {"w", "u", "z", "q", "x"}} </code></pre> </blockquote> <p>You can see see that <code>SortBy</code> has swapped the positions of <code>"i"</code>/<code>"e"</code> and <code>"q"</code>/<code>"x"</code> in the lists so it is not a minimal reordering. This can be corrected however with <a href="https://stackoverflow.com/a/3332690/618728">a different syntax for <code>SortBy</code></a>:</p> <pre><code>SortBy[lists\[Transpose], {First}]\[Transpose] </code></pre> <blockquote> <pre><code>{{3, 6, 7, 8, 8}, {"b", "f", "m", "i", "e"}, {"w", "u", "z", "q", "x"}} </code></pre> </blockquote> <p>This syntax also speeds up <code>SortBy</code>, but not enough to be competitive with <code>Ordering</code>:</p> <pre><code>SortBy[{a, b, c}\[Transpose], {First}]\[Transpose] // timeAvg </code></pre> <blockquote> <p>0.0001248</p> </blockquote> https://mathematica.stackexchange.com/questions/7679/-/7699#7699 5 Answer by István Zachar for Sort lists according to the order of another István Zachar https://mathematica.stackexchange.com/users/89 2012-06-30T07:35:17Z 2012-06-30T08:34:07Z <p>This is a <strong>more general solution</strong> that I came up with some time ago to solve some rearrangement problems. I'm pretty sure that it is slower than any of the solutions above (as it uses <code>ReplacePart</code>), but it is general enough to deal with any kind of ragged partitions. Usage: <code>partitionAs</code> sorts and partitions a list just as a reference list <code>ref</code> is ordered and partitioned.</p> <pre><code>partitionAs[list_, ref_] := Module[{ord = Ordering@Flatten@ref, pos = Position[ref, Except[_List | List]]}, ReplacePart[ref, Thread[pos -&gt; Flatten[list][[ord]]]]]; ref = {{2, {9}, 0}, {3, 7}, 6, {4, {8, 5}, 1}} list = {"A", "B", {"C", "D"}, "E", {"F", "G"}, "H", "I", "J"}; partitionAs[list, ref] </code></pre> <blockquote> <p><code>{{2, {9}, 0}, {3, 7}, 6, {4, {8, 5}, 1}}</code></p> <p><code>{{"C", {"J"}, "A"}, {"D", "G"}, "I", {"F", {"E", "H"}, "B"}}</code></p> </blockquote>