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.

Let's say I have a list like:

{"good element 1", "bad element 1", "good element 2", "good element 3", "bad element 2", ...}

I would like to build a function that will display each element of this list one at a time, and if I press the "left" key it will append the focus element to a list of "good" elements, whereas if I press "right" it will append it to another list of bad elements.

Can Mathematica do this and with what kind of functions? I usually come up with a bit of code of my own but this time I really don't know with what functions to start from.

share|improve this question
add comment

2 Answers

up vote 8 down vote accepted

The most direct hack I can think of, which gives you the right functions for a better implementation:

list = {"good element 1", "bad element 1", "good element 2", 
  "good element 3", "bad element 2"};

i = 1;
good = {};
bad = {};
EventHandler[
 InputField[Dynamic[If[i <= Length[list], list[[i]], "End"]], 
  Enabled -> False], {"LeftArrowKeyDown" :> 
   If[i <= Length[list], 
    AppendTo[bad, list[[i++]]]]}, {"RightArrowKeyDown" :> 
   If[i <= Length[list], AppendTo[good, list[[i++]]]]}]

Mathematica graphics

Note that you have to click on the input field first.

share|improve this answer
    
Just perfect. So of course mathematica can do it! –  su1 Oct 21 '13 at 11:04
add comment

Here's a different strategy. I've heard people refer to this as "the Mathematica way" and it's certainly much more flexible in many situations. The gist of it is that instead of putting each element into a different list as we work through them, I "mark" them by changing their heads. When I want a list of "good" items or "bad" items, I collect them based on what head I've given them. By keeping them in their original list, I can easily go back and modify to my heart's content without any problem at all.

The advantages are more visible the more advanced the code gets, so I've built an example with some extra functionality to demonstrate. Instead of the arrow keys I'm using y/u and j/k because Mathematica didn't already have functionality tied to those keys.

First let's define some functions:

getName[category[name_, category_]] := name
getCategory[category[name_, category_]] := category
printList[list_] := Rasterize@ImagePad[
   GraphicsRow[
    getName[#] & /@ list[[1 ;; 5]],
    Background -> (Switch[getCategory[#], "Uncategorized", White, "Good", LightGreen, "Bad", LightRed] & /@ list),
    ImageSize -> {500, 50},
    AspectRatio -> 50/500,
    Frame -> All
    ], 50, White]
interactiveList[list_] := (
  l = category[#, "Uncategorized"] & /@ RotateRight[list];
  Dynamic@EventHandler[
    Show[printList[l], Graphics[{
       Text["The graphics element has to be selected to use the keyboard controls.", {200, 120}],
       Text["y/u to go left/right. j/k to designate good/bad and move to the left.", {195, 30}]
       }]],
    {
     {"KeyDown", "u"} :> (l = RotateLeft[l]),
     {"KeyDown", "y"} :> (l = RotateRight[l]),
     {"KeyDown", "j"} :> (l[[2]] = category[getName[l[[2]]], "Good"]; l = RotateLeft[l]),
     {"KeyDown", "k"} :> (l[[2]] = category[getName[l[[2]]], "Bad"]; l = RotateLeft[l])
     }
    ]
  )
showList[list_, attr_] := Cases[list, category[name_, attr] :> name]

To run this:

interactiveList[CountryData[]]

screen

Use the keyboard keys according to the instructions. To get a list of items designated "Good", "Bad" or "Uncategorized":

showList[l, "Good"]
showList[l, "Bad"]
showList[l, "Uncategorized"]

(A further improvement would be to localize variables.)

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.