3
$\begingroup$

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.

$\endgroup$

2 Answers 2

8
$\begingroup$

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.

$\endgroup$
1
  • $\begingroup$ Just perfect. So of course mathematica can do it! $\endgroup$
    – Sulli
    Commented Oct 21, 2013 at 11:04
1
$\begingroup$

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.)

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