5
$\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$
2
  • 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$ Commented Sep 30, 2018 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$ Commented Sep 30, 2018 at 4:08

3 Answers 3

5
$\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$
1
  • $\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
    Commented Sep 30, 2018 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$
1
  • $\begingroup$ Also: Normal @ Merge[Total] @ list $\endgroup$
    – eldo
    Commented Sep 5, 2023 at 8:15
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 and acknowledge you have read our privacy policy.

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