# List Manipulation on Array with subscript elements

I am trying to write a function which operates on an array with subscripted elements.

As an example i have the array a={$1_3$,$2_2$,$4_1$}, which means i have 3 amounts of value 1, 2 amounts of value 2 and 1 amount of value 4. If the subscripted amount reaches 0, then the element has to be dropped from the array.

Now i need a function

edit[a_,lower_,raise_]:=...


with lower_ being an array of elements which shall be decreased by 1 and raise_ being the array of elements which should be increased by 1. These two arrays have to contain the value and not the position of the element which should be changed.

So if i would call the function with

edit[{Subscript[1, 3], Subscript[2, 2], Subscript[4, 1]}, {1, 1, 4}, {2, 5}]


the output should be

{Subscript[1, 1],Subscript[2, 3], Subscript[5, 1]}


because

• the value 1 has to be decreased 2 times, leaving it with the amount 1
• the value 4 has to be decreased once, thus the amount reaches 0 and it has to be dropped
• the value 2 has to be increased once, increasing the amount to a total of 3
• the value 5 has to be increased once, and since its not in the list yet, it has to be added

I want to use subscript because it makes it easy to read and seems to behave like a normal 2 dimensional array, but i am open to good alternatives.

You can do it with "classic" functions Tally and GatherBy

edit[a_, lower_, raise_] :=
DeleteCases[#, _[_, 0]] &[
Subscript[#[[1, 1]], Total@#[[All, 2]]] & /@ GatherBy[#, First] &@
Join[a, Subscript @@@ (-Tally[-lower]), Subscript @@@ Tally@raise]]

edit[{Subscript[1, 3], Subscript[2, 2], Subscript[4, 1]}, {1, 1, 4}, {2, 5}]
(* {Subscript[1, 1], Subscript[2, 3], Subscript[5, 1]} *)

• @RunnyKine I thought that it is invalid input. Anyway, one can add c_ /; c <= 0 instead of 0 in DeleteCases. Commented Oct 5, 2014 at 12:10
• You're probably right that it's invalid input. +1 Commented Oct 5, 2014 at 12:11
• all 3 answers were pretty good, thanks a lot
– kon
Commented Oct 8, 2014 at 7:51
• @ybeltukov Is it possible to return an empty array when invalid input is made? Invalid Input would also be raising a value lower then 1. ex: edit[{Subscript[1, 1], Subscript[3, 1]},{1,1,2},{0}]
– kon
Commented Oct 12, 2014 at 13:21

Here is an approach using Association for Version 10+.

edit[a_, lower_, raise_] := Subscript @@@ Normal@DeleteCases[#, 0] &@
Merge[{#, #2, #3}, Total] &[<|Rule @@@ a|>, -Counts[lower], Counts[raise]]


Use:

edit[{Subscript[1, 3], Subscript[2, 2], Subscript[4, 1]}, {1, 1, 4}, {2, 5}]


$\left\{1_1,2_3,5_1\right\}$

• Is Association already implemented in Mathematica 8.0? Or which Version do i need to run it?
– kon
Commented Oct 5, 2014 at 11:33
• @kon. This is for Version 10 and above. Sorry, I didn't know you were on Version 8. Commented Oct 5, 2014 at 11:33
• Actually its my fault for not mentioning it, but unfortunately i cant use it and i dont think i can convince my university to upgrade to version 10 for me.
– kon
Commented Oct 5, 2014 at 11:37
• @kon. You can download a trial version which is free for 30 days and try it out or use the Wolfram programming cloud. Commented Oct 5, 2014 at 11:39
• Very nice code! I also thought to use associations but my code is not nearly as good. (I forgot entirely about Counts for one thing.) Commented Oct 5, 2014 at 22:46
lst = {Subscript[1, 3], Subscript[2, 2], Subscript[4, 1]};


$\left\{1_3,2_2,4_1\right\}$

ClearAll[foo, editFX];
foo = Flatten[GatherBy[Join[#1, Subscript @@@ Tally[#2] ], First] /.
{Subscript[x_, a_], Subscript[x_, b_]} :>
(Subscript[x, a + #3 b] /. Subscript[_, 0] :> Sequence[])] &;
editFX[lst_, arg1 : {___}, arg2 : {___}] := With[{t = foo[lst, arg1, -1]}, foo[t, arg2, 1]];

editFX[lst, {1, 1, 4}, {2, 5}]


$\left\{1_1,2_3,5_1\right\}$

Or

ClearAll[editFX2];
editFX2 = Fold[foo[#1, First@#2, Last@#2] &, #, {{#2, -1}, {#3, 1}}] &;
editFX2[lst, {1, 1, 4}, {2, 5}]


$\left\{1_1,2_3,5_1\right\}$

• Nice. I like it. +1 Commented Oct 5, 2014 at 12:44
• Thank you @RunnyKine.
– kglr
Commented Oct 5, 2014 at 12:46