1
$\begingroup$

I have a 4 list of pairs as

P1 = {{4, 17}, {19, 32}, {-5, 8}};
P2 = {{16, 29}, {31, 44}, {40, 53}};
P3 = {{55, 68}, {64, 77}, {79, 92}};
P4 = {{76, 89}, {88, 101}, {91, 104}};

and I combine this 4 list by

Q = Join[P1, P2, P3, P4]

and then i sort it with respect to first element in pairs b

Sort[Q, #1[[1]] < #2[[1]] &]

But I want to trace also the appearing pairs in last result with the corresponding list. That is {-5, 8} is came from P1. How to do this. Please help. Thank you.

$\endgroup$
3
$\begingroup$

Many ways to do this. Read the documentation re: associations, etc. Here's a quick and simple way. Note I changed your symbols to lowercase initials (bad idea to use capital initials, risks clashing with built-in symbols). Since you do not specify if duplicate pairs can appear in multiple lists, I've not accounted for that, caveat lector...

p1 = {{4, 17}, {19, 32}, {-5, 8}};
p2 = {{16, 29}, {31, 44}, {40, 53}};
p3 = {{55, 68}, {64, 77}, {79, 92}};
p4 = {{76, 89}, {88, 101}, {91, 104}};
q = Join[p1, p2, p3, p4];
qs = SortBy[q, First];

(* here, strings are used to represent the symbols assigned to your lists *)
qs
qs /. Join @@ (Thread[ToExpression[#] -> #] & /@ {"p1", "p2", "p3","p4"})
(* put these "together" *)
Thread[%% -> %]

{{-5, 8}, {4, 17}, {16, 29}, {19, 32}, {31, 44}, {40, 53}, {55, 68}, {64, 77}, {76, 89}, {79, 92}, {88, 101}, {91, 104}}

{"p1", "p1", "p2", "p1", "p2", "p2", "p3", "p3", "p4", "p3", "p4", \ "p4"}

{{-5, 8} -> "p1", {4, 17} -> "p1", {16, 29} -> "p2", {19, 32} -> "p1", {31, 44} -> "p2", {40, 53} -> "p2", {55, 68} -> "p3", {64, 77} -> "p3", {76, 89} -> "p4", {79, 92} -> "p3", {88, 101} -> "p4", {91,104} -> "p4"}

| improve this answer | |
$\endgroup$
3
$\begingroup$

Consider initializing differently.

p[1] = {{4, 17}, {19, 32}, {-5, 8}};
p[2] = {{16, 29}, {31, 44}, {40, 53}};
p[3] = {{55, 68}, {64, 77}, {79, 92}};
p[4] = {{76, 89}, {88, 101}, {91, 104}};

SortBy[Join @@ Table[# -> i & /@ p[i], {i, 4}], First]

(* {{-5, 8} -> 1, {4, 17} -> 1, {16, 29} -> 2 ... *)
| improve this answer | |
$\endgroup$
  • $\begingroup$ @Kuba I know first elements are obtained here by #[[1,1]]&, but isn't a pair of elements (via First only) compared by their first elements and on a tie by second? I don't know if OP needs were stated that precisely. :) $\endgroup$ – BoLe Aug 4 '16 at 8:42
2
$\begingroup$

Create a new list with the list name and then Sort.

s1 = P1 /. {x_, y_} -> {x, y, "P1"}
s2 = P2 /. {x_, y_} -> {x, y, "P2"}
s3 = P3 /. {x_, y_} -> {x, y, "P3"}
s4 = P4 /. {x_, y_} -> {x, y, "P4"}

Q1 = Join[s1, s2, s3, s4]
Q2 = Sort[Q1, #1[[1]] < #2[[1]] &]
Q3 = Q2[[All, {1, 2}]]

Q2 will show the sorted list with list name and Q3 will show only the elements.

| improve this answer | |
$\endgroup$
1
$\begingroup$

As the previous answers show, in order to "trace" the data you are sorting, you must, soon or late, build a new data structure where each data element "knows" where it comes from.

1. Something like: {{{4,17},"p1"}, {{19,32},"p1"}, ... is probably the simplest structure to deal with. You can directly apply Sort or SortBy on it. For example:

q={{{4, 17}, "p1"}, {{19, 32}, "p1"}, {{-5, 81}, "p1"}, {{16, 29}, "p2"},
 {{31, 44}, "p2"}, {{40, 53}, "p2"}};

SortBy[q,#[[1,1]]&]
{{{-5, 81}, "p1"}, {{4, 17}, "p1"}, {{16, 29}, "p2"}, {{19, 32}, "p1"},
 {{31, 44}, "p2"}, {{40, 53}, "p2"}}

If you can't or for some reasons you don't want to build such a list from the start, you can build it automatically from the existing definitions of p1, p2 ... Here is a way to do it with this function:

tag[x_List, func_: List] := 
 Module[{symbols = ToString /@ Unevaluated /@ (Unevaluated@x)}, 
  Join @@ MapThread[Thread[func[##]] &, {ToExpression@#, #} &@symbols]]

SetAttributes[tag, HoldAll]

then for example:

p1 = {{4, 17}, {19, 32}, {-5, 81}};
p2 = {{16, 29}, {31, 44}, {40, 53}};

q = tag[{p1, p2}]
{{{4, 17}, "p1"}, {{19, 32}, "p1"}, {{-5, 81}, "p1"}, {{16, 29}, "p2"},
 {{31, 44}, "p2"}, {{40, 53}, "p2"}}

You can also build a "subscripted" form of the list with :

q = tag[{p1, p2}, Subscript]

enter image description here

This form will work exactly the same way as previously with Sort or SortBy (SortBy[q,#[[1,1]]&])

2. Dataset

This is most probably an overkill, but you might be interested in converting your data to a more structured Dataset. I let you explore the documentation and examples about it on this site and give you just an idea of how Dataset works. For example, let convert the previous q list to such a dataset:

q = tag[{p1, p2}];
ds = Dataset[
  AssociationThread @@@ Thread[{{"val", "symb"}, q}, List, {-1}]]

enter image description here

Then, to sort by the the first element in the "val" column:

ds[SortBy[#val[[1]] &]]
(* or : SortBy[ds, #val[[1]] &] *)

enter image description here

Then you can extract the column you want, chain with other action, ...

| improve this answer | |
$\endgroup$

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.