2

I have a list of data in javascript that looks like this:

[[152, 48, 'http://www.google.com'], 
 [198, 47, 'http://www.stackoverflow.com'], 
 [199, 45, 'http://www.apple.com']]

I am using flot to create a plot, and am trying to pass this third value to access a hyperlink from the point. As such, I am trying to lookup the third value of each list by using the first two as the lookup keys (i.e., [[x,y,hyperlink],[x2,y2,hyperlink2]], click on a point, then use the appropriate (x,y) to find the corresponding hyperlink)

Is there anyway to do this, or do I need to pass some dictionaries for x and y to javascript, then find the common variable from the two lists that were looked up? In python I know you could do a filter of list on the x value with itemgetter, then lookup a link corresponding to the y value. But I know almost nothing about js, so could a solution to ID-ing with (x,y) be given, or if not possible or advised, then a solution to taking two lists of (from x and y vals) and find a common value (if multiple, just one, anyone)?

Ray Toal
  • 86,166
  • 18
  • 182
  • 232
David__
  • 365
  • 2
  • 6
  • 20

3 Answers3

5

You can make use of the Array .filter() method to figure out if any elements match the supplied x and y. (Note that IE didn't support .filter() until version 9, but MDN has a shim that you can include).

var data = [[152, 48, 'http://www.google.com'],
            [198, 47, 'http://www.stackoverflow.com'],
            [199, 45, 'http://www.apple.com']];

function getURLForPoint1(x, y) {
    var p = data.filter(function(el) {
        return (el[0] === x && el[1] === y);
    });
    if (p.length === 1) return p[0][2];
    // else 0 or more than 1 elements mathced so return undefined
}

Alternatively you can create a dictionary object up front and then do future lookups from the dictionary:

var getURLForPoint2 = function() {
    var dataDictionary = {}, i;
    for (i = 0; i < data.length; i++)
       dataDictionary[data[i][0]+" "+data[i][1]] = data[i][2];

    return function(x, y) {
       return dataDictionary[x + " " + y];
    };
}();

Either way I've coded it so that if you ask for a point that isn't in the list you'll get undefined back, but obviously you can change that to return an empty string or throw an exception or whatever you like.

alert(getURLForPoint1(198, 47));    // 'http://www.stackoverflow.com'
alert(getURLForPoint2(198, 47));    // 'http://www.stackoverflow.com'
alert(getURLForPoint2(4, 5));       // undefined

Demo of both: http://jsfiddle.net/WdSAz/

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
2

Sorry, no shortcut way to do it in js except to just loop through the list and find the one that has the matching "x" and "y" value.

However, depending on how large your list is (and whether or not this list will be used for something else...) you could restructure the data to make it more efficient. For instance, do a structure like (assumed possible to have for instance x1, y1 vs x1, y2)

x1 > y1 > url
x1 > y2 > url
x2 > y1 > url
etc...

then you can immediately jump to the 2nd lvl "y" list by the "x" index, and the only looping would be how many "y" values share the same "x" value

edit:

actually if you wanna take it a step further with reorganizing the data, you could do something like this:

<script type='text/javascript'>
var list = {
  1 : {
    1 : 'foobar 1,1',
    2 : 'foobar 1,2'
  },
  2 : {
    1 : 'foobar 2,1',
    2 : 'foobar 2,2'
  },
};

</script>

which will allow you to do for instance this

var x = 1;
var y = 2;
alert(list[x][y]);
CrayonViolent
  • 32,111
  • 5
  • 56
  • 79
  • Note that attempting to retrieve points where the `x` co-ordinate is not in your `list` would give a JS error because then `list[x]` would be undefined and you can't do `undefined[y]`. – nnnnnn Jun 24 '12 at 00:41
  • well yes, it is good practice to check if it exists before using it; that's not really directly part of this exercise... and there are plenty of ways to check if it exists. – CrayonViolent Jun 24 '12 at 00:44
  • What I mean is that the test for existence would be a two-step process (and I was pointing that out because it is a bit fiddly): you'd have to test if `list[x]` is defined before you can test if `list[x][y]` is defined otherwise you don't just get `undefined` back, you get a JS error that stops the code executing. But yes, if the whole thing was wrapped up in an accessor function then obviously the function would handle that... – nnnnnn Jun 24 '12 at 01:11
1

somthing like this maybe

  var findX = 198
  var findY = 47
  var targetUrl
  for (var i=0; i<arr.length; i++)
  {
      for (var j=0; j<arr[i].length; j++)
      {
          if (findX = j[0] && findY == j[1])
          {
              targetUrl = j[2]
          } 
      }
  }
Graham.Fraser
  • 369
  • 2
  • 12
  • is called a jagged array i think. Its a type of multi-dimensional array commonly found in java from what i remember. – Graham.Fraser Jun 23 '12 at 23:53
  • 3
    `for ... in` loops are meant to iterate over object properties and can be dangerous to use for arrays. Always use `for(var i=0; i – Trevor Jun 23 '12 at 23:57
  • 2
    Why do you have a nested loop? A single loop will do it - note that your `j` variable is not an array so `j[0]` won't work. (Note also that you probably intended `==` (not `=`) in your `if`.) – nnnnnn Jun 24 '12 at 00:24