Hot answers tagged

30

Caveat lector: Incorrect results are generated by this solution, e.g., sortByColumn[{{"a", 1, 1}, {"b", 2, 3}, {"a", 3, 2}}, {1, 1, -1}] returns {{"a", 1, 1}, {"b", 2, 3}, {"a", 3, 2}} when the correct result is obviously {{"a", 1, 1}, {"a", 3, 2}, {"b", 2, 3}} I've commented on the answer to bring it to the attention of ...


30

This is probably because by default Sort doesn't just use numerical values, it includes structure information as well. From the doc: Numeric expressions are sorted by structure as well as numerical value: In[1]:= Sort[{Sqrt[2], 1, 2, 1/Sqrt[2]}] Out[1]= {1, 2, 1/Sqrt[2], Sqrt[2]} Sort by numerical value only: In[2]:= Sort[{Sqrt[2], 1, 2, ...


29

You can use combination of Part and Ordering as list1[[ Ordering @ list2 ]] to sort list1 in the order of list2. Examples: {list1, list2, list3} = {{1, 3, 2}, {a, b, c}, {x, y, z}}; list2[[ Ordering @ list1 ]] gives {a, c, b} and list3[[ Ordering @ list1 ]] gives {x, z, y} EDIT: Using with lists of lists, to sort the entire array based on the ...


26

n = 100; (*number of points*) s = RandomSample@Range@n; (*the initial set*) (*some aux functions*) head[{x_, xs___}] := Select[{xs}, # <= x &]; tail[{x_, xs___}] := Select[{xs}, # > x &]; (*qsort function modified for sowing the information needed*) qsort[{}] = {}; qsort[l : {x_, ___}] := Module[{lh, lt}, (Sow@{l, lh = head@l, x, lt = tail@l}; ...


26

If you're looking for a way to sort the colors in such a way as to make them seem the least discontinuous, then one way to think of it is that each color is a point in a space endowed with a distance metric (either the CIELAB 1976 or the CIELAB2000 perceptual metrics), and you are trying to find a shortest tour that visits each point. We can do that with ...


25

If you want to keep the rows and your preferences of ordering is first ascending, second descending and third ascending, you can use SortBy: SortBy[data, {#[[1]],-#[[2]],#[[3]]}&]


25

This is implemented in SortBy: Because this function does not perform a pairwise compare, you would need to be able to recast your sort function to produce a canonical ordering. On the upside, if you are able to do so it will be far more efficient than Sort. f1 = Mod[#, 4] &; f2 = Mod[#, 7] &; SortBy[Range@10, {f1, f2}] {#, f1@#, f2@#} & ...


22

lists = {list1, list2, list3} = {{1, 3, 2}, {a, b, c}, {x, y, z}}; Another option SortBy[lists\[Transpose], First]\[Transpose] {{1, 2, 3}, {a, c, b}, {x, z, y}}


20

With: dat = {{10, b, 30}, {100, a, 40}, {1000, b, 10}, {1000, b, 70}, {100, b, 20}, {10, b, 70}}; Perhaps most directly: Cases[dat, {_, _, Max@dat[[All, 3]]}] More approaches: Last @ SplitBy[SortBy[dat, {#[[3]] &}], #[[3]] &] Pick[dat, #, Max@#] &@dat[[All, 3]] Reap[Fold[(If[#2[[3]] >= #, Sow@#2]; #2[[3]]) &, dat]][[2, 1]] Of ...


20

arr = {29400., 28200., 22300., 20900., 20300., 19800., 17400., 16600., 16300., 16100., 15500., 15300., 15300., 15200., 15100., 14900., 14700., 14700., 14400., 13900.} From here RANK gives duplicate numbers the same rank. However, the presence of duplicate numbers affects the ranks of subsequent numbers. For example, in a list of integers sorted in ...


19

This is short: Last /@ Sort[{Characters@#, #} & /@ names] {"~/Hex_6.dat", "~/Hex_12.dat", "~/Hex_24.dat", "~/Hex_48.dat", "~/Hex_96.dat", "~/Hex_192.dat"} Alternatively: Last /@ Sort[{ToExpression[StringJoin[Select[Characters@#, DigitQ]]], #} & /@ names]


19

In general SortBy can do pretty much anything that Sort does; in some cases, possibly better or faster. You can find many comparisons on this site if you just search for both function names. I also disagree with @user21382 that his task could not be expressed elegantly in SortBy form: not only can it be done, I would actually argue that it could be done ...


18

Maybe Partition[Sort@list, 2, 1] giving {{1, 3}, {3, 4}, {4, 5}, {5, 7}}


18

Yes, there is! Szabolcs showed a use of GatherBy in an inverted fashion as a substitute for a conventional decorate-and-sort. It proved both syntactically and computationally efficient. By using that method in place of the decorate-and-sort in this application we can use Ordering directly, and also eliminate Part which was needed to strip the decoration: ...


17

Ordering and Part is more efficient than SortBy and Transpose and it can also be done in one pass as I will demonstrate. I create three lists of different type as described in the question: a = RandomInteger[999, 500]; b = RandomReal[1, 500]; c = CharacterRange["a", "z"] ~RandomChoice~ 500; I use the timeAvg function for testing: SortBy[{a, b, ...


17

Something like this might be helpful. It replaces the unsorted list of symbols with a sorted list, lets Mathematica rearrange the expression in the normal way, and then applies a HoldForm before replacing the symbols back again. reorderSymbols[expr_, symbols_List] := With[{s = symbols}, HoldForm[Evaluate[expr /. Thread[s -> Sort@s]]] /. Thread[Sort@s ...


16

No, this is not a bug, and Ordering does not give a wrong answer. Quoting the documentation of Sort, Sort[list,p] applies the function p to pairs of elements in list to determine whether they are in order. The default function p is OrderedQ[{#1, #2}] &. As you can see, Sort (and Ordering) compares using OrderedQ, not Less. OrderedQ uses a ...


16

You could do this: GatherBy[list, Last][[All, 1]] ~SortBy~ Last (* {{d, 3}, {b, 3.04}, {a, 3.1}} *)


15

I think this question admits an elegant solution. Here is my attempt: define a special wrapper: ClearAll[sortFun]; sortFun /: SortBy[expr_, sortFun[funs_List, partFun_]] := SortBy[expr, Map[Composition[#, partFun] &, funs]]; Now, mySort := {StringTake[#, 1] &, ToExpression@StringDrop[#, 1] &} and SortBy[{"T3","T14","T1","E2"}, ...


15

Rather than it being "too big" for the pattern matcher, the problem here is because of the use of //. which applies the rule repeatedly till the result no longer changes (i.e. the list is sorted). In other words, the issue is that of the complexity of the algorithm you're using (//. with ___) rather than the programming paradigm that you've chosen (pattern ...


14

As you said in your comment that you just want a well displayed formula, I suggest using Row to force specific orders. A rough example will look like following, you might want to adjust the priority level according to your needs: expr = A^2 e^2 SuperMinus[\[Phi]] SuperPlus[\[Phi]] + A e SuperMinus[\[Phi]] SuperPlus[\[Phi]] Subscript[c, 2 w] Subscript[g, ...


14

According to The Chicago Manual of Style, para. 18.57/18.58, punctation marks are ignored. 18.57 The letter-by-letter system. In the letter-by-letter system, alphabetizing continues up to the first parenthesis or comma; it then starts again after the punctuation point. Word spaces and all other punctuation marks are ignored. Both open and ...


14

You can use ReplaceList with a helper function which has the Orderless attribute: ClearAll[f]; SetAttributes[f, Orderless]; ReplaceList[f[a, b, c], f[a___, b___, c___] :> {{a}, {b}, {c}}] // DeleteCases[#, {}, -1] & // Union // Column The DeleteCases and Union are required because the output from ReplaceList includes the empty list {} as a ...


14

SortBy[l, {First@#, -ToCharacterCode@Last@#} &] (*{{1, "u"}, {1, "d"}, {2, "u"}, {2, "d"}, {3, "u"}, {3, "d"}, {4, "u"}, {4, "d"}, {5, "u"}, {5, "d"}, {6, "u"}, {6, "d"}}*) Or the same, but slightly shorter code SortBy[l, {#, -ToCharacterCode@#2} &@@#&] Edit The following uses the same sorting strategy but is much faster (by using this): ...


13

I share Leonid's reservations about basing the sort on simple string length. I would use a similar Ordering method, but I would parse things differently. Consider this test set: names = {"~/Hex_12.dat", "~/Hex_192.dat", "~/Oct_99.dat", "~/Hex_014.dat", "~/Hex_24_17.dat", "~/Hex_24_5.dat", "~/Hex_48.dat", "~/Hex_6.dat", "~/Hex_96.dat", ...


13

Position is looking for an exact match (pseudo-SameQ), rather than a numeric one. You will get the result you want with: Position[data[[All, 1]], _?(# == xlow &)] Or: Position[data[[All, 1]], x_ /; x == xlow] Generally you should use Equal (short form ==) any time you are trying to mach Real numbers, to allow for small rounding errors. Using the ...


13

Using Simon's data: In[6]:= datelist = {"29/02/2008", "15/12/2007", "06/09/2007", "06/10/2008", "05/03/2007", "24/01/2010", "19/06/2009", "03/11/2009", "02/02/2010", "25/12/2009"}; We can just sort the data by the absolute time: In[7]:= SortBy[datelist, AbsoluteTime[{#, {"Day", "Month", "Year"}}] &] Out[7]= {"05/03/2007", "06/09/2007", ...


12

Here a similar symbol replacement method to the one Simon used, in my own style. reorder[expr_, pats_List] := Module[{h, rls}, rls = MapIndexed[x : # :> h[#2, x] &, pats]; HoldForm @@ {expr /. rls} /. h[_, x_] :> x ] This definition allows you, within the standard limits of pattern matching expressions (e.g. FullForm) of course, to ...


12

A simple string-based approach is to swap the order of day/month/year, do the Sort and then swap back again: (* Example data *) datelist = DateString[# + AbsoluteTime[{2007, 01, 01}], {"Day", "/", "Month", "/", "Year"}] & /@ RandomInteger[10^8, 10] {"29/02/2008", "15/12/2007", "06/09/2007", "06/10/2008", "05/03/2007", "24/01/2010", ...


12

SeedRandom[42]; haystack = RandomReal[1, 6300]; AbsoluteTiming[ f = Nearest[haystack -> Range@Length@haystack]; {f[.3, 1], haystack[[f[.3, 1]]]}] (* -> {0.015625, {{3123}, {0.300033}}} *) Of course in this case most of the time is expended calculating the nearest function. If your points aren't changing from one use to the next, the time for ...



Only top voted, non community-wiki answers of a minimum length are eligible