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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.