CristianC
CristianC

Reputation: 301

Javascript get corresponding key/value from object

I have an object which might look like this:

var nicknames = []
nicknames.push({id:"100", name:"john", id2:"200", name2:"max"});

but the object might also look like this:

nicknames.push({id:"200", name:"max", id2:"100", name2:"john"});

so key and values might be switched.

How can I get the name and id "john" and "100" if providing name of "max" or id of "200"?

Upvotes: 4

Views: 2152

Answers (5)

tomloprod
tomloprod

Reputation: 7862

Maybe this will be useful for you.

var nicknames= [ {id:"100", nickname:"John"}, {id:"200", nickname:"Michael"} ];

function getByName(arr, value) {
   for (var i=0, iLen=arr.length; i<iLen; i++) {
      if (arr[i].nickname == value) return arr[i];
   }
}

var object = getByName(nicknames, "John");

// Will show '100'
alert(object.id); 

You can see this in action here: http://jsfiddle.net/b1yL28at/

Upvotes: 1

jpl
jpl

Reputation: 367

In you keep this data representation, you'll have to loop over your entire array, which is inefficient.

I think you should (if you can) change your data representation and opt for an associative array, where keys are pairs id-name and values are nicknames. This way it becomes easy and efficient to find matches.

Or, maybe even better because it reduces redundancy, two associative arrays: the first one for id/names; the second for nickname matches (keys are ids and values are ids as well).

Upvotes: 1

RobG
RobG

Reputation: 147363

If the data structure is as described and here are exactly two names and IDs, and the name and ID sets are unique in each object, then the following should do the job:

var nicknames = [{id:"100", name:"john", id2:"200", name2:"max"},
                 {id:"300", name:"tim", id2:"400", name2:"fred"}];

function getOther(nameOrId) {
  var nickname;

  for (var i=0, iLen=nicknames.length; i<iLen; i++) {
    nickname = nicknames[i];

    if (nickname.id == nameOrId || nickname.name == nameOrId) {
      return [nickname.id2, nickname.name2];
    }
    if (nickname.id2 == nameOrId || nickname.name2 == nameOrId) {
      return [nickname.id, nickname.name];
    }
  }
}

console.log(getOther('max')); // ["100", "john"]

console.log(getOther('100')); // ["200", "max"]

console.log(getOther('400')); // ["300", "tim"]

It just looks for a match with the name or id within a nickname pair and if finds one, returns the other. It could be made more generic.

If you want to keep Douglas Crockford happy and avoid the loop by using an ES5 feature, then:

function getOther(nameOrId) {
  var result;

  nicknames.some(function (nickname) {
    if (nickname.id == nameOrId || nickname.name == nameOrId) {
      return result = [nickname.id2, nickname.name2];
    }
    if (nickname.id2 == nameOrId || nickname.name2 == nameOrId) {
      return result = [nickname.id, nickname.name];
    }
  });
  return result;
}

But I don't see the point, it's exactly the same number of lines of code and no clearer (IMHO of course).

Upvotes: 1

thefourtheye
thefourtheye

Reputation: 239443

If you are going to do more lookups, then the best solution I could think of is to build an inverse map, like this

var nicknames = []

nicknames.push({
    id: "100",
    name: "john",
    id2: "200",
    name2: "max"
});

var idIndex = {},
    nameIndex = {};

nicknames.forEach(function(currentNickName) {

    idIndex[currentNickName.id] = {
        id: currentNickName.id2,
        name: currentNickName.name2
    };
    idIndex[currentNickName.id2] = {
        id: currentNickName.id,
        name: currentNickName.name
    };

    nameIndex[currentNickName.name] = {
        id: currentNickName.id2,
        name: currentNickName.name2
    };
    nameIndex[currentNickName.name2] = {
        id: currentNickName.id,
        name: currentNickName.name
    };

});

And then would look like

console.log(nameIndex, idIndex);

this

{ john: { id: '200', name: 'max' }, max: { id: '100', name: 'john' } }
{ '100': { id: '200', name: 'max' }, '200': { id: '100', name: 'john' } }

And then you can search like this

console.log(nameIndex["max"]);
// { id: '100', name: 'john' }
console.log(nameIndex["john"]);
// { id: '200', name: 'max' }
console.log(idIndex["100"]);
// { id: '200', name: 'max' }
console.log(idIndex["200"]);
// { id: '100', name: 'john' }

Upvotes: 1

Barmar
Barmar

Reputation: 780734

var found_name, found_id;
for(var i = 0; i < nicknames.length; i++) {
    var nn = nicknames[i];
    if (nn.name == "max" || nn.id = "200") {
        found_name = nn.name2;
        found_id = nn.id2;
        break;
    } else if (nn.name2 == "max" || nn.id2 = "200") {
        found_name = nn.name;
        found_id = nn.id;
        break;
    }
}

Upvotes: 1

Related Questions