JavaScript从对象中获取对应的键/值

4

我有一个对象,可能看起来像这样:

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

但对象也可能是这样的:
nicknames.push({id:"200", name:"max", id2:"100", name2:"john"});

键和值可能会被交换。

如果提供"max"的名称或"200"的ID,我如何获取名称和ID"john""100"


1
没有内置的函数可以按对象值搜索。你必须编写一个循环。 - Barmar
该对象是否恰好包含两个名称和两个ID? - RobG
是的,有两个名称和两个ID,但它们可能在不同的键中(id1或id2 / name1或name2)。 - CristianC
那么,如果给定名称或ID值,您想要获取另一个ID和名称吗? - RobG
5个回答

1
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;
    }
}

Barmar,你的答案非常好用。非常感谢。我也会检查其他答案。 - CristianC

1
也许这对你有用。
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); 

您可以在这里看到实际效果:http://jsfiddle.net/b1yL28at/


1
如果您需要进行更多的查找操作,那么我能想到的最佳解决方案是构建一个反向映射表,如下所示。
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
    };

});

然后看起来像这样

console.log(nameIndex, idIndex);

这个。
{ john: { id: '200', name: 'max' }, max: { id: '100', name: 'john' } }
{ '100': { id: '200', name: 'max' }, '200': { id: '100', name: 'john' } }

然后你可以像这样搜索。
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' }

1
如果数据结构如上所述,且每个对象中恰好有两个名称和ID,并且名称和ID集在每个对象中都是唯一的,则以下内容应该能够完成任务:
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"]

它只是在昵称对中查找名称或ID匹配项,如果找到,则返回另一个匹配项。可以使其更通用。
如果您想让Douglas Crockford感到满意并避免使用循环,可以使用ES5功能:
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;
}

但我看不出有什么意义,代码行数完全相同,也没有更加清晰易懂(当然这只是我的个人观点)。


1
如果您继续使用这种数据表示方式,您将不得不循环遍历整个数组,这是低效的。
我认为您应该(如果可以的话)更改数据表示方式,并选择关联数组,其中键是id-name对,值是昵称。这样查找匹配项就变得简单和高效。
或者,甚至更好的方法是减少冗余,使用两个关联数组:第一个用于id/names;第二个用于昵称匹配(键是ids,值也是ids)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接