6
$\begingroup$

I have two lists a and b of the same length. And another list a2 which contains all elements from a and some others. Now I want to construct a list b2 so that for the shared elements between a2 and a, the corresponding elements in b2 and b are the same, and for those elements in a2 but not a, the values in b2 should be placeholder 0.

Example:

a = {1, 2, 5, 8};
b = {10, 20, 50, 80};
a2 = {1, 2, 4, 5, 8, 9};
(*Output b2={10,20,0,50,80,0}*)

I know how to achieve this in C-like languages, so I'm wondering if there is a better way of doing this in Mathematica. Thanks!

P.S. a and a2 are both ordered. And no duplicate exsists in either list, if it helps.

$\endgroup$

6 Answers 6

5
$\begingroup$

For all versions:

Replace[a2, Append[Thread[a -> b], _ -> 0], 1]
{10, 20, 0, 50, 80, 0}

If you need speed look at Dispatch.

For versions 10.0 or later Association functionality is fast and concise:

Lookup[AssociationThread[a, b], a2, 0]
{10, 20, 0, 50, 80, 0}

Tersely Thread works in place of AssociationThread but it causes a redundant evaluation:

Lookup[Thread[a -> b], a2, 0]
{10, 20, 0, 50, 80, 0}
$\endgroup$
1
  • 2
    $\begingroup$ Waw, nice to see you back and to see such nice answer. Man when are finishing your book! $\endgroup$ Jan 14, 2016 at 21:35
3
$\begingroup$
Fold[Insert[#1, 0, #2] &, b, Position[Map[Position[a, #] &, a2], {}]]

{10, 20, 0, 50, 80, 0}

Probably faster with large lists:

Fold[Insert[#1, 0, #2] &, b, Position[a2, Alternatives @@ Complement[a2, a]]]
$\endgroup$
2
$\begingroup$

The most obvious :

If[MemberQ[a, #], b[[Position[a, #][[1, 1]]]], 0] & /@ a2

{10, 20, 0, 50, 80, 0}

$\endgroup$
2
$\begingroup$

Some pure "mathematical" ad hoc:

a2 /. Thread[a -> b] /. Thread[Complement[a2, a] -> 0]

{10, 20, 0, 50, 80, 0}

$\endgroup$
1
$\begingroup$
mia = MapIndexed[Rule[#2, t[#1]] &, a];
mib = MapIndexed[Rule[#2, #1] &, b];
mic = MapIndexed[Rule[t[#1], #2] &, a2];
Normal@SparseArray[mib /. (mia /. mic), Length[a2]]
(*{10, 20, 0, 50, 80, 0}*)
$\endgroup$
0
$\begingroup$
 b2 = Sort[Join[{#, 0} & /@ Complement[a2, a], Join[Partition[Riffle[a, b], 2]]]][[All, 2]]

{10, 20, 0, 50, 80, 0}

$\endgroup$

Your Answer

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

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