Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I've got this simple problem with two lists. I select some items from a list, but I want to visualize the difference between the previous list and the list that I create with Select.

For instance:

a = {{7, 0, 0, 2}, {0, 0, 2, 5}, {10, 4, 8, 7}, {7, 1, 9, 2}, {1, 3, 6, 7}, 
     {6, 9, 2, 9}, {2, 0, 7, 1}, {2, 5, 1, 1}, {9, 6, 4, 0}, {9, 9, 2, 8}};
b = Select[a, #[[4]] > 5 &];

I want a list that compare the two lists in this manner

results = 
  {{7, 0, 0, "-"}, {0, 0, 2, "-"}, {10, 4, 8, 7}, {7, 1, 9, "-"}, {1, 3, 6, 7}, 
   {6, 9, 2, 9}, {2, 0, 7, "-"}, {2, 5, 1, "-"}, {9, 6, 4, "-"}, {9, 9, 2, 8}};
share|improve this question
2  
An easy way is : {#[[1]], #[[2]], #[[3]], If[#[[4]] > 5, #[[4]], "-"]} & /@ a. –  b.gatessucks Mar 25 '13 at 11:34
add comment

4 Answers 4

results = a /. {x__, _?(# <= 5 &)} :> {x, "-"}

or

a /. {x___, y_ /; y <= 5} :> {x, "-"}

or

b = Select[a, #[[4]] > 5 &]; 
results=If[MemberQ[b, #], #, Flatten@{#[[;; -2]], "-"}] & /@ a

or

results=a; MapAt[If[# <= 5, "-", #] &, results, {All, -1}]

to get

(* {{7, 0, 0, "-"}, {0, 0, 2, "-"}, {10, 4, 8, 7}, {7, 1, 9, "-"}, {1, 3, 6, 7},
  {6, 9, 2, 9}, {2, 0, 7, "-"}, {2, 5, 1, "-"}, {9, 6, 4, "-"}, {9, 9, 2, 8}} *)
share|improve this answer
    
I was going to post a /. {x___, y_} /; y <= 5 -> {x, "-"} –  belisarius Mar 25 '13 at 11:40
    
@belisarius, fwiw, of the three variants of ReplaceAll, a /. {x___, y_} /; y <= 5 -> {x, "-"}, a /. {x___, y_ /; y <= 5} :> {x, "-"} and ` a /. {x___, _?(# <= 5 &)} :> {x, "-"}` the middle one seems to be marginally faster for large lists. –  kguler Mar 25 '13 at 12:09
    
Interesting, I wonder why :) –  belisarius Mar 25 '13 at 12:27
    
@kguler; @b.gatessucks; @belisarius Thanks a lot. You're very kind and solved my problem in a very smart way. I hope I'll be usefull to you. –  meriens Mar 25 '13 at 13:43
add comment

Why Select? Traverse the list with Map and replace the appropriate part of each sublist if it fails your test.

Map[If[#[[4]] > 5, #, ReplacePart[#, 4 -> "-"]] &, a]
share|improve this answer
add comment

Using Reap and Sow with tags, you can get both the selected elements and the diff output in one go:

{selected, diff} = Last@Reap[
    Cases[a, x_ :> If[x[[4]] > 5, Sow[x, "selected"], 
        Sow[ReplacePart[x, 4 -> "-"], "diff"]]], {"selected", "diff"}] ~Flatten~ 1

(* {{{10, 4, 8, 7}, {1, 3, 6, 7}, {6, 9, 2, 9}, {9, 9, 2, 8}}, 
    {{7, 0, 0, "-"}, {0, 0, 2, "-"}, {7, 1, 9, "-"}, {2, 0, 7, "-"}, {2, 5, 1, "-"}, {9, 6, 4, "-"}}} *)

If you want the selected elements too in your diff output, then all you need to do is to also tag them "diff", i.e., change the first Sow above to Sow[x, {"selected", "diff"}].

share|improve this answer
add comment

If you have both lists prepared already, you can use SequenceAlignment and then post-process:

Flatten[
  SequenceAlignment[a, b] /. {deleted_List, {}} :> 
      Map[MapAt["-" &, #, -1] &, deleted], 
  1]

This however may not be the optimal solution for really large lists in terms of performance.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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