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"?
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"?
Share Improve this question asked Jan 2, 2015 at 11:04 CristianCCristianC 3013 silver badges11 bronze badges 4- 1 There's nothing built-in that searchest by object values. You have to write a loop. – Barmar Commented Jan 2, 2015 at 11:07
- Does the object contain exactly two names and two ids? – RobG Commented Jan 2, 2015 at 11:08
- Yes, two names and two ids, but they might be in different keys (id1 or id2/ name1 or name2) – CristianC Commented Jan 2, 2015 at 11:11
- So given either a name or id value, you want to get back the other id and name? – RobG Commented Jan 2, 2015 at 11:29
5 Answers
Reset to default 1var 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;
}
}
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' }
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).
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 bees 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).
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/b1yL28at/
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745153490a4613974.html
评论列表(0条)