12
$\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 Answers 9

12
$\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$
8
$\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$
8
$\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$
1
  • $\begingroup$ Great ... thank you $\endgroup$
    – lio
    Jun 29, 2018 at 17:49
6
$\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$
6
$\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$
5
$\begingroup$

Using two-argument form of Last:

h = Map[Append[#, Last[#, 0]] &];

Example:

h @ {{}, {1, 2}, {}, {2, 4, 3}, {5, 4, 3, 2}, {}}
{{0}, {1, 2, 2}, {0}, {2, 4, 3, 3}, {5, 4, 3, 2, 2}, {0}}
$\endgroup$
1
  • 1
    $\begingroup$ Thanks, very useful for me in in many other cases too $\endgroup$
    – eldo
    Oct 21, 2023 at 9:29
3
$\begingroup$

Using SequenceReplace:

lst = {{}, {1, 2}, {}, {2, 4, 3}, {5, 4, 3, 2}, {}}
SequenceReplace[lst, {{{}} :> {0}, {{a__, b_}} :> {a, b, b}}]

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

$\endgroup$
3
$\begingroup$
list = {{}, {1, 2}, {}, {2, 4, 3}, {5, 4, 3, 2}, {}};

1.

add[{a__, b_}] := {a, b, b}
add[{}] := {0}

add /@ list

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

2.

ReplaceAt[list, {{} :> {0}, {a__, b_} :> {a, b, b}}, All]

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

ReplaceAt was introduced with V 13.1

$\endgroup$
2
$\begingroup$

Another way is to use Cases and If as follows:

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

Cases[list, x_ :> If[x == {}, Append[x, 0], Append[x, Last@x]]]

(*{{0}, {1, 2, 2}, {0}, {2, 4, 3, 3}, {5, 4, 3, 2, 2}, {0}}*)

Or using ReplaceList:

ReplaceList[#, {{a___, b_} :> Splice@{a, b, b}, {} -> 0}] & /@ 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 and acknowledge you have read our privacy policy.

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