6
$\begingroup$

(Edit: I mean 'differentiate' as in telling the difference between two things, not as in f'(x) )

I have n series of numbers, let's say two for example, with some "empty" spaces between the numbers, and I want to add them element-wise. The problem is, I need to differentiate between the numbers, which can include 0, and the empty spaces, so I cannot use 0 as a placeholder in the empty spaces.

For example, using 'E' as the empty space character (edit: oops forgot E was a built-in symbol, it can be something else), 'adding' the following two series (in reality, they'd be much longer and be more than two series being added):

{-2, E, E, 0, E, -1, E}
{-1, E, 0, E, E,  1, 5}

I want to get

{-3, E, 0, 0, E,  0, 5}

So basically, the rules are:

In the ith position of the series (1D Tables) being added:

  1. If all the members are 'E', then put 'E' in the ith position of the result series

  2. Otherwise, add the numbers like normal, ignoring the Es

So now that I've defined what I'm wanting to do, can anyone think of an elegant way to implement it? Only thing I can think of is by defining my own custom adding function, but it seems like there should be a more clever way to do it?

Thanks.

$\endgroup$
2
  • 2
    $\begingroup$ E is the base of natural logarithms $\endgroup$
    – unlikely
    Commented Mar 24, 2016 at 7:09
  • 1
    $\begingroup$ Why insist on using Plus[]? You can repurpose one of the undefined operators like CirclePlus[] with your addition rules... $\endgroup$ Commented Mar 24, 2016 at 7:25

5 Answers 5

5
$\begingroup$

Perhaps the most simple and elegant solution to this is to let all of your numbers be real and use the integer zero for "empty". Then the built in Plus does just what you want:

 {-2., 0, 0, 0., 0, -1., 0} + {-1., 0, 0., 0, 0, 1., 5.} 

{-3., 0, 0., 0., 0, 0., 5.}

convert for display:

 % /. {0 -> e  , x_Real :> Round[x]}

{-3, e, 0, 0, e, 0, 5}

$\endgroup$
6
$\begingroup$

This works, though it's not as terse as I would have hoped.

list1 = {-2, e, e, 0, e, -1, e}
list2 = {-1, e, 0, e, e, 1, 5}

I use e because E is a built in symbol.

Replace[Thread[{list1, list2}], {{e ..} :> e, {x__} :> Total[{x} /. e :> 0]}, {1}]
{-3, e, 0, 0, e, 0, 5}

Initially I tried

e + x_ ^:= x

But when we have e + 0, this evaluates to just e before the UpValues rule has a chance to turn this into 0.

Per suggestion of @J.M., we can use CirclePlus (or the infix form which is typed by sequentially pressing Esc+C+++Esc) to make an addition function that follows your definitions.

SetAttributes[CirclePlus, {Flat, Orderless, OneIdentity, Listable}]
e /: e⊕x_ := x
(a : Except[e])⊕(b : Except[e]) := a + b

Then

list1 ⊕ list2 -> {-3, e, 0, 0, e, 0, 5}

It is also possible to use TagSetDelayed to make the built-in Plus to behave like you want, but only if you abandon using the integer 0 and use the floating point 0. instead.

list1 = N@list1
list2 = N@list2
e /: e + 0. := 0.
e /: e + e := e
list1 + list2
{-3., e, 0., 0., e, 0., 5.}
$\endgroup$
2
$\begingroup$
lists = {
   {-2, Missing[], Missing[], 0, Missing[], -1, Missing[]},
   {-1, Missing[], 0, Missing[], Missing[], 1, 5}
   };

With[{n = Length@lists},
 Replace[Total[lists], {
   n Missing[] :> Missing[], _.*Missing[] + x_. :> x
   }, {1}]
 ]

Result:

{-3, Missing[], 0, 0, Missing[], 0, 5}
$\endgroup$
3
  • $\begingroup$ The hard part about this question is getting the rule Missing[] + 0 -> 0 to work. Sadly, the lhs persistently evaluates to just Missing[]. $\endgroup$
    – LLlAMnYP
    Commented Mar 24, 2016 at 7:17
  • $\begingroup$ @LLlAMnYP True, fixed (I hope) $\endgroup$
    – unlikely
    Commented Mar 24, 2016 at 7:29
  • $\begingroup$ That works (if you sum up the lists only once and know how many of them there will be). It's harder if you want to add another list to the result later. $\endgroup$
    – LLlAMnYP
    Commented Mar 24, 2016 at 7:48
2
$\begingroup$
a = {-2, e, e, 0, e, -1, e};
b = {-1, e, 0, e, e, 1, 5};

f[OrderlessPatternSequence[e, a_]] := a
f[a_, b_] := a + b

MapThread[f, {a, b}]

{-3, e, 0, 0, e, 0, 5}

A more general solution

a = {-2, x, e, 0, e, -1, e};
b = {-1, x, 0, e, e, 1, 5};

g[OrderlessPatternSequence[a_Symbol, b_]] := b
g[a_, b_] := a + b

MapThread[g, {a, b}]

{-3, x, 0, 0, e, 0, 5}

$\endgroup$
2
  • $\begingroup$ (+1) Clever way to handling this question! Happy New Year, @eldo! :-) $\endgroup$ Commented Jan 1 at 2:55
  • 1
    $\begingroup$ Thank you, and also a Happy New Year to you :) $\endgroup$
    – eldo
    Commented Jan 1 at 8:02
1
$\begingroup$

Grabbing the @eldo's general example:

a1 = {-2, e, e, 0, e, -1, e};
b1 = {-1, e, 0, e, e, 1, 5};

a2 = {-2, x, e, 0, e, -1, e};(*By @eldo*)
b2 = {-1, x, 0, e, e, 1, 5};

Another approach to handling this special adding is as follows:

g[l_] := If[MatchQ[l, {Repeated[_Symbol, {2}]}], DeleteDuplicates[l], 
         DeleteCases[l, _Symbol]]

specialAdding[a_?VectorQ, b_?VectorQ] := Plus @@ # & /@ g /@ Transpose@{a, b}

 specialAdding[a1, b1]

 (*{-3, e, 0, 0, e, 0, 5}*)

 specialAdding[a2, b2]

 (*{-3, x, 0, 0, e, 0, 5}*)
$\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.