10
$\begingroup$

If I have the following list:

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

How can I add the last element of each sublist to each sublist?

The results should be (empty sublists should be filled with zeros, here I know that I can use the replacement /.{}->{0}):

{{0}, {1, 2, 2}, {0}, {2, 4, 3, 3}, {5, 4, 3, 2, 2}, {0}}
$\endgroup$
9
$\begingroup$
lst = {{}, {1, 2}, {}, {2, 4, 3}, {5, 4, 3, 2}, {}} ;
Join[lst, (lst /. {} -> {0})[[All, {-1}]], 2] 

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

Also

ClearAll[f]; f[{}] = {0}; f[{a___, b_}] := {a, b, b};
f /@ {{}, {1, 2}, {}, {2, 4, 3}, {5, 4, 3, 2}, {}}

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

Timings:

ClearAll[f0, f1, f2, f3, f4, f5];
f0[{}] = {0}; f0[{a___, b_}] := {a, b, b}; 
f1 = f0 /@ # &;
f2 = Join[#, (# /. {} -> {0})[[All, {-1}]], 2] &;
f3 = Replace[#, {{a___, last_} :> {a, last, last}, {} -> {0}}, -1] &; (*MarcoB *)
f4 = Replace[#, {a___, b_} | {} :> {a, b, b + 0}, {1}] &; (* Mr.Wizard *)
f5 = # /. {{} -> {0}, _ :> # ~ Join~{#[[-1]]}} & /@ # &; (* Fraccalo *)
f6 = Append[#, If[# == {}, 0, #[[-1]]]] & /@ # &; (* GIM *)

SeedRandom[1]
testlst = RandomInteger[10, #] & /@ RandomInteger[10, 1000000];
t1 = First[AbsoluteTiming[r1 = f1@testlst;]];
t2 = First[AbsoluteTiming[r2 = f2@testlst;]];
t3 = First[AbsoluteTiming[r3 = f3@testlst;]];
t4 = First[AbsoluteTiming[r4 = f4@testlst;]];
t5 = First[AbsoluteTiming[r5 = f5@testlst;]];
t6 = First[AbsoluteTiming[r6 = f6@testlst;]];
Equal[r1, r2, r3, r4, r5, r6]

True

Grid[Prepend[SortBy[Transpose[{{"f1", "f2", "f3", "f4", "f5", "f6"},
  {t1, t2, t3, t4, t5, t6}}], Last], {"function", "timing"}], Dividers -> All]

enter image description here

$\endgroup$
5
$\begingroup$

A single-Rule method using Alternatives:

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

Replace[in, {a___, b_} | {} :> {a, b, b + 0}, {1}]
{{0}, {1, 2, 2}, {0}, {2, 4, 3, 3}, {5, 4, 3, 2, 2}, {0}}

Some additional examples that may help in understanding this code:

$\endgroup$
5
$\begingroup$
Replace[
  {{}, {1, 2}, {}, {2, 4, 3}, {5, 4, 3, 2}, {}}, 
  {{a___, last_} :> {a, last, last}, {} -> {0}},
  -1
]

(* Out:  {{0}, {1, 2, 2}, {0}, {2, 4, 3, 3}, {5, 4, 3, 2, 2}, {0}} *)
$\endgroup$
  • $\begingroup$ Great ... thank you $\endgroup$ – lio Jun 29 '18 at 17:49
4
$\begingroup$

You can also use Append and an If statement, and this is fairly quick: if the list is empty, append a 0, else append the last element in the list, and map this function across your input:

Append[#, If[# == {}, 0, #[[-1]]]] & /@ {{}, {1, 2}, {}, {2, 4, 3}, {5, 4, 3, 2}, {}}

For timing, use AbsoluteTiming to get:

AbsoluteTiming[
 Append[#, If[# == {}, 0, #[[-1]]]] & /@ {{}, {1, 2}, {}, {2, 4,3}, {5, 4, 3, 2}, {}}]

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

$\endgroup$
3
$\begingroup$

One line solution, just for fun:

# /. {{} -> {0}, _ :> #~Join~{#[[-1]]}} & /@ list

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

$\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.