I've got two lists that contain an element identifier and a number:
list1 = Transpose[{{"c", "a", "b"}, {2, 1, 1}}]
list2 = Transpose[{{"a", "b", "c", "e", "f"}, {2, 2, 2, 2, 2}}]
listdesired = Transpose[{{"a", "b", "c", "e", "f"}, {1, 1, 0, 2, 2}}]
I'd like to know an efficient method to produce listdesired
from list1
and list2
. In this case, the desired output is found by subtracting the integer in list1 from the item in list2 that has the same identifier ('a', 'b', 'c', ...).
Update
The solution that worked for me is reproduced below since it is currently in a comment and I would like the answer to persist. The answer that has been accepted works just fine as well.
KeyValueMap[List]@*Subtract @@ KeyUnion[{Rule @@@ #2, Rule @@@ #}, 0 &] &[list1, list2]
Transpose@*KeyValueMap[List]@*Subtract @@ KeyUnion[{Rule @@@ #2, Rule @@@ #}, 0 &] &[list1, list2]
? $\endgroup$Transpose
composition since I want the pairs, but yep! And thanks for usingRule @@@ list
as I've been banging my head trying to remember that for some time now. $\endgroup$Sort@Join[list1, list2] GatherBy[%, First] Transpose /@ %
$\endgroup$Key
is another name forIdentifier
and there is a nice data structure that builds upon this calledAssociation
. $\endgroup$Join[list1,list2]//GatherBy[#,First]&//Map@(PadLeft[#,{2,2}]&)//Map@({#[[2,1]], #[[2,2]] - #[[1,2]]}&)//Sort
AlternativelyJoin[list1,list2]//GatherBy[#,First]&//Map@({#[[2,1]], #[[2,2]] - #[[1,2]]}&@*(PadLeft[#,{2,2}]&))//Sort
$\endgroup$