4
$\begingroup$

I have a large list of the following form

{{1, 2} -> -1, {1, 1} -> 1, {1, 2} -> -1, {1, 6} -> 1}

and I want to combine all of the pairs x->y that share the same x value by adding up their y values. For the above example I want to have

{{1, 2} -> -2, {1, 1} -> 1, {1, 6} -> 1}

and I want to do it using patterns and ReplaceRepeated command. I tried the following code:

{{1, 2} -> -1, {1, 1} -> 1, {1, 2} -> -1, {1, 6} -> 1} //. 
  HoldPattern[{x_ -> y_, a___, x_ -> z_}] -> {x -> y + z, a}

Can anybody tell me why above code is not working and how can I do it using rules?

$\endgroup$
  • 1
    $\begingroup$ //. is not really intended for combinations like these. Try Merge[]: Normal[Merge[{{1, 2} -> -1, {1, 1} -> 1, {1, 2} -> -1, {1, 6} -> 1}, Total]] $\endgroup$ – J. M. will be back soon Sep 30 '18 at 4:03
  • $\begingroup$ Thanks @J.M.issomewhatokay. You answer is correct. However, I mostly want to learn about patterns and I wanna know how can extract such patterns. $\endgroup$ – The Legend of 1991 Sep 30 '18 at 4:08
4
$\begingroup$

In general, there may (or may not) be preceding, intervening, and subsequent elements in the list that must handled using BlankNullSequence

{{1, 2} -> -1, {1, 1} -> 1, {1, 2} -> -1, {1, 6} -> 1} //. {start___, 
   x_ -> y1_, middle___, x_ -> y2_, end___} :> {start, x -> y1 + y2, middle, end}

(* {{1, 2} -> -2, {1, 1} -> 1, {1, 6} -> 1} *)
$\endgroup$
  • $\begingroup$ Because it is only coincidental that the first element of your list is one of interest (i.e., matching LHS of rule). In general, any number of non-matching elements could be at the start. $\endgroup$ – Bob Hanlon Sep 30 '18 at 4:51
6
$\begingroup$

You could use GroupBy:

Normal @ GroupBy[
    {{1,2}->-1,{1,1}->1,{1,2}->-1,{1,6}->1},
    First -> Last,
    Total
]

{{1, 2} -> -2, {1, 1} -> 1, {1, 6} -> 1}

$\endgroup$
3
$\begingroup$

You can use SparseArray setting the system sub-option "TreatRepeatedEntries" to Plus:

SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> Plus}];
sa = SparseArray[{{1, 2} -> -1, {1, 1} -> 1, {1, 2} -> -1, {1, 6} -> 1}];
SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> First}];

Thread[sa@"NonzeroPositions" -> sa@ "NonzeroValues"]

{{1, 2} -> -2, {1, 1} -> 1, {1, 6} -> 1}

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