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
    $\begingroup$ E is the base of natural logarithms $\endgroup$ – unlikely Mar 24 '16 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$ – J. M. is away Mar 24 '16 at 7:25
3
$\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$
4
$\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$
1
$\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$
  • $\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 Mar 24 '16 at 7:17
  • $\begingroup$ @LLlAMnYP True, fixed (I hope) $\endgroup$ – unlikely Mar 24 '16 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 Mar 24 '16 at 7:48

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.