7
$\begingroup$

I have a list of values, e.g., {1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5}. I delete the duplicates with

DeleteDuplicates[{1, 1, 1 ,2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5}];

{1, 2, 3, 4, 5}

I want to perform some calculations on each value and at the end reverse the process of deleting.

From Tally I know, how often the elements appear:

Tally[{1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5}];

{{1, 3}, {2, 2}, {3, 2}, {4, 5}, {5, 1}}

Now, from the calculations I have the new list {12, 14, 15, 16, 17}. I want to reverse the process of DeleteDuplicates on this list. Means: {{12,3},{14,2},{15,2},{16,5},{17,1}} -> So, that I get:

{12, 12, 12, 14, 14, 15, 15, 16, 16, 16, 16, 17}.

I want to do that, because the calculations take very long and I want to calculate duplicates two times.

$\endgroup$
2
  • 4
    $\begingroup$ Are you familiar with the concept of memoization in Mathematica? It would allow you to map a function over the original list but only perform the long calculation once for each unique value. $\endgroup$ Nov 6, 2015 at 20:42
  • $\begingroup$ Are the starting list and the second list always sorted? $\endgroup$ Nov 7, 2015 at 0:01

4 Answers 4

7
$\begingroup$
tal = {{1, 3}, {2, 2}, {3, 2}, {4, 5}, {5, 1}};

lis = {12, 14, 15, 16, 17};

Flatten @ MapThread[Table[#1, {#2}] &, {lis, Last /@ tal}]

{12, 12, 12, 14, 14, 15, 15, 16, 16, 16, 16, 16, 17}

Or

Flatten[ConstantArray @@@ Transpose[{lis, Last /@ tal}]]
$\endgroup$
5
$\begingroup$

The following can be used also for unsorted lists:

SeedRandom[42];
l = RandomInteger[{3, 8}, 10]
l /. Thread[# -> expensive/@ #] &@Union@l

(* {6, 6, 5, 3, 7, 3, 7, 3, 7, 4} *)
(* {expensive[6], expensive[6], expensive[5], expensive[3], expensive[7],
    expensive[3], expensive[7], expensive[3], expensive[7], expensive[4]} *)
$\endgroup$
3
$\begingroup$

Given your initial list:

mylist = {1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5};

another way to translate your approach is for example:

q[x_] := (Print["Computing..."]; f[x]);

Join @@ KeyValueMap[ConstantArray, KeyMap[q, Counts[mylist]]]
Computing...
Computing...
Computing...
Computing...
Computing...
{f[1],f[1],f[1],f[2],f[2],f[3],f[3],f[4],f[4],f[4],f[4],f[4],f[4],f[5]}

unless you prefer use the excellent memoization approach proposed by @Simon Woods:

p[x_] := p[x] = (Print["Computing..."];f[x]);
p /@ mylist
Computing...
Computing...
Computing...
Computing...
Computing...
{f[1],f[1],f[1],f[2],f[2],f[3],f[3],f[4],f[4],f[4],f[4],f[4],f[4],f[5]}

In both cases, you can see that computation of f took place only 5 times and not as many times as the number of elements in the list.

$\endgroup$
1
$\begingroup$
tal = {{1, 3}, {2, 2}, {3, 2}, {4, 5}, {5, 1}};
lis = {12, 14, 15, 16, 17};
MapThread[Sequence @@ ConstantArray[#1, #2[[2]]] &, {lis, tal}]
$\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.