2
$\begingroup$

Suppose I have two lists of the following form:

List1 = {{"c", 3.5}, {"a", 2.2}, {"d", 1.2}, {"b", 0.5}};
List2 = {{"a", 1}, {"b", 3}, {"c", 5}, {"d", 9}};

I want to create a new list that essentially matches the letters and gives me the two numerical values for the letters, it should give the following:

List3={{"a", 1, 2.2}, {"b", 3, 0.5}, {"c", 5, 3.5}, {"d", 9, 1.2}}

I’m probably missing a very straightforward solution to this, but I’m struggling to find it.

$\endgroup$

5 Answers 5

2
$\begingroup$
lis1 = {{"c", 3.5}, {"a", 2.2}, {"d", 1.2}, {"b", 0.5}}
lis2 = {{"a", 1}, {"b", 3}, {"c", 5}, {"d", 9}}
lis = Join[lis1, lis2]
h = Union@Map[First, lis] (*to pick the letters*)

And now

Map[ Function[{x}, Flatten@{x, Cases[lis, {x, y_} :> y]}], h]

enter image description here

I bet there are 9 more ways to do this in Mathematica.

$\endgroup$
3
$\begingroup$
KeyValueMap[Prepend[#2, #1] &, Merge[{Rule @@@ List2, Rule @@@ List1}, Identity]]
(* {{"a", 1, 2.2}, {"b", 3, 0.5}, {"c", 5, 3.5}, {"d", 9, 1.2}} *)

If your actual data isn't sorted nicely, and you want a sorted result:

SortBy[
  KeyValueMap[Prepend[#2, #1] &, Merge[{Rule @@@ List2, Rule @@@ List1}, Identity]], 
  First]
$\endgroup$
3
$\begingroup$

If you formulate your lists as associations,

A1 = Association @@ Rule @@@ List1
(*    <|"c" -> 3.5, "a" -> 2.2, "d" -> 1.2, "b" -> 0.5|>    *)
A2 = Association @@ Rule @@@ List2
(*    <|"a" -> 1, "b" -> 3, "c" -> 5, "d" -> 9|>            *)

then they can be merged directly:

Merge[{A1, A2}, Identity]
(*    <|"c" -> {3.5, 5}, "a" -> {2.2, 1}, "d" -> {1.2, 9}, "b" -> {0.5, 3}|>    *)
$\endgroup$
2
$\begingroup$
l1 = {{"c", 3.5}, {"a", 2.2}, {"d", 1.2}, {"b", 0.5}};

l2 = {{"a", 1}, {"b", 3}, {"c", 5}, {"d", 9}};

Using the third argument of GroupBy:

f = Values[
Sort@GroupBy[Join[#1, #2], First, 
  DeleteDuplicates@*Join @@ 
    ReverseSortBy[#, MatchQ[#[[2]], _Integer] &] &]] &;

f[l1, l2]

{{"a", 1, 2.2}, {"b", 3, 0.5}, {"c", 5, 3.5}, {"d", 9, 1.2}}

Or using GroupBy and SortBy:

f = Values@GroupBy[Sort@Join[#1, #2], 
    First, {#1[[1]], Splice@SortBy[#2, ! IntegerQ[#] &]} & @@ Thread@# &] &;

f[l1, l2]

{{"a", 1, 2.2}, {"b", 3, 0.5}, {"c", 5, 3.5}, {"d", 9, 1.2}}

Or using Association:

sortPair = SortBy[#, ! IntegerQ[#] &] &@*Identity;
assoc = Partition[Sort[Association@*Rule @@@ Join @@ #], Length@#] &;

Merge[assoc@{l1, l2}, sortPair]

(*<|"a" -> {1, 2.2}, "b" -> {3, 0.5}, "c" -> {5, 3.5}, "d" -> {9, 1.2}|>*)

KeyValueMap[{#1, Splice@#2} &]@%

(*{{"a", 1, 2.2}, {"b", 3, 0.5}, {"c", 5, 3.5}, {"d", 9, 1.2}}*)
$\endgroup$
2
$\begingroup$
alist = {{"c", 3.5}, {"a", 2.2}, {"d", 1.2}, {"b", 0.5}};
blist = {{"a", 1}, {"b", 3}, {"c", 5}, {"d", 9}};

Join[alist, blist] // SortBy[First] // 
  SequenceCases[#, k : {{a_, _} ..} :> {a, Sequence @@ Last /@ k}] & //
  SortBy[Position[alist, First@#] &]

Join[alist, blist] // Map[Apply[Rule]] // Merge[Identity] // 
 KeyValueMap[{#1, Sequence @@ #2} &]

Merge[Rule @@@ Join[alist, blist], Identity] // 
 KeyValueMap[{#1, Sequence @@ #2} &]

{{"c", 3.5, 5}, {"a", 1, 2.2}, {"d", 1.2, 9}, {"b", 0.5, 3}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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