6
$\begingroup$

I have a simple functional programming question: I have a simple EdgeList defined in Mathematica, I would like to modify the value of certain element of the list based on a condition. I see how to define the conditional If, but I don't know how to "scan" my EdgeList and modify the elements so that it returns another EdgeList. Could someone show me a simple example on how to accomplish this in Mathematica?

$\endgroup$
2
  • $\begingroup$ You could try some Rule-based approach {a \[UndirectedEdge] b, b \[UndirectedEdge] c, c \[UndirectedEdge] a} /. a \[UndirectedEdge] x_ :> a \[UndirectedEdge] y $\endgroup$
    – ssch
    Dec 30, 2012 at 12:43
  • $\begingroup$ @ssch Thanks for the input, however I cannot use a rule-based approach because I need to call a function behind the rules. And, as far as I know, when you apply the rule it will only call the function once for every edges matching the rule. In fact, what I want to do is to rename some edge: every edge with name "ABC" will become "ABC 1", "ABC 2", ... $\endgroup$
    – afentis
    Dec 30, 2012 at 12:48

1 Answer 1

5
$\begingroup$

First a list of UndirectedEdge

list = MapIndexed[UndirectedEdge[First[#2], #1] &, CharacterRange["a", "e"]]

Let's say you want to change all edges where the head is OddQ then you could do something like

list /. e : UndirectedEdge[a_, b_] :> If[OddQ[a], UndirectedEdge[a, b <> "1"], e]

The trick is to apply the rule to all edges but only change those which match your If condition. Maybe a bit clear is to use Map and first define a function which modifies exactly one UndirectedEdge

f[e : UndirectedEdge[a_, b_]] :=  If[OddQ[a], UndirectedEdge[a, b <> "1"], e]
f /@ list

There are many more ways and the more experienced users will probably use such a map with a pure Function where you don't have to define f separately.

Update for increasing numbers

To Map a function usually modifies every element of a list but the function itself only works on the data without knowing how many elements it has processed or other global things. To stick with Map we have to introduce some (at least locally defined) global variable which counts. I will use i here which is increased every time a the edge was modified. Additionally, I define the Function for modifying an edge in-place with Function and e is the edge-parameter:

Block[{i = 1},
 Function[e, 
   If[OddQ[First[e]], UndirectedEdge[First[e], Last[e] <> ToString[i++]], e]] /@ list
 ]
$\endgroup$
1
  • $\begingroup$ Looks great, thanks a lot :) if I may, just a little "side question", I see that in your example you append "1" to the edge value, how would you attempt to rewrite f so that it increments the number every time it's called? (a1, a2, ...) this is a problem I am facing at the moment... $\endgroup$
    – afentis
    Dec 30, 2012 at 13:37

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.