【问题标题】:Search through array in an object using javascript without using a loop使用javascript在对象中搜索数组而不使用循环
【发布时间】:2019-01-26 08:32:27
【问题描述】:

我想找到一个更好、更优雅的解决方案,而不是使用 2 次迭代来查找对象中的值。我查看了在数组中搜索的函数,例如 find、indexOf,但想知道我可以在不使用 for 或 forEach 的情况下搜索对象。

假设我想找到所有游泳者。到目前为止我得到了什么。

members = [
  { name: "Sue", hobby: ["Swimming", "Running", "Dancing"] },
  { name: "Sam", hobby: ["Cars", "Travelling"] },
  { name: "John", hobby: ["Reading", "Swimming"] },
  { name: "Rob", hobby: ["Running", "Coding"] },      
];
function findSwimmers(members, hobby) {      
  let swimmers = [];      
  members.forEach(function (e){        
    e.hobby.forEach(function (element){          
      if (element.toLowerCase() === hobby.toLowerCase()) {
        swimmers.push(e);
      }
    });
  });
  return swimmers;
}

【问题讨论】:

  • 任何 搜索数组的方法都会以某种方式使用循环...

标签: javascript arrays object search


【解决方案1】:

您可以将filtersome 结合使用,方法是将回调 函数作为参数传递。

let members = [
  { name: "Sue", hobby: ["Swimming", "Running", "Dancing"] },
  { name: "Sam", hobby: ["Cars", "Travelling"] },
  { name: "John", hobby: ["Reading", "Swimming"] },
  { name: "Rob", hobby: ["Running", "Coding"] },      
];

function findSwimmers(members, hobby) {      
  return members_swimming = members.filter(({hobby}) => hobby.some(item => item == "Swimming"));
                                
}

console.log(findSwimmers(members, "Swimming"));

【讨论】:

  • 建议合并 OP 的 toLowerCase(或类似的)而不是硬编码 "Swimming"。甚至可能提到String#localeComparesensitivity: "base"(如果有)。
  • 返回名称效果很好,但我想返回对象,就像我的函数一样......
  • 我不知道你为什么添加 map 和 assignment。 return 语句可以简化为:return members.filter(member => member.hobby.some(item => item == hobby)); 我认为这就是 OP 想要的。
  • @PWT,只需删除map 方法。
【解决方案2】:

你可以用一行来实现:

let swimmers = members.filter(person => person.hobby.includes('Swimming'));

【讨论】:

  • OP 的代码允许不区分大小写的匹配。以上没有。
  • 返回名称效果很好,但我想返回对象,就像我的函数一样......
  • 这应该会返回一个包含名称和爱好(以及您想要添加的任何其他内容)的对象数组,其中爱好包括游泳,我认为这是您正在寻找的?但是 - 正如已经指出的那样,我没有考虑任何大小写不匹配,所以我的解决方案目前不适合目的。
【解决方案3】:

您可以将Array.filter()Array.map() 用于解构:

var members = [
  { name: "Sue", hobby: ["Swimming", "Running", "Dancing"] },
  { name: "Sam", hobby: ["Cars", "Travelling"] },
  { name: "John", hobby: ["Reading", "Swimming"] },
  { name: "Rob", hobby: ["Running", "Coding"] },      
];
var swimmers = members.filter(({hobby}) => hobby.includes('Swimming')).map(({name}) => name);
console.log(swimmers)

【讨论】:

  • OP 的代码允许不区分大小写的匹配。以上没有。此外,OP 的代码返回成员对象,而不仅仅是他们的名字。 map 这里没有位置。
【解决方案4】:

任何解决方案都将涉及循环。唯一的问题是循环是在你的代码还是你调用的函数中。

在您的情况下,filtersome 似乎是可以使用的工具:

function findSwimmers(members, hobby) {
  hobby = hobby.toLowerCase();
  return members.filter(member =>
    member.hobby.some(h => h.toLowerCase() === hobby)
  );
}

您可能需要不同的函数名称。 :-)

现场示例:

const members = [
  { name: "Sue", hobby: ["Swimming", "Running", "Dancing"] },
  { name: "Sam", hobby: ["Cars", "Travelling"] },
  { name: "John", hobby: ["Reading", "Swimming"] },
  { name: "Rob", hobby: ["Running", "Coding"] },      
];
function findSwimmers(members, hobby) {
  hobby = hobby.toLowerCase();
  return members.filter(member =>
    member.hobby.some(h => h.toLowerCase() === hobby)
  );
}

console.log(findSwimmers(members, "swimming"));
.as-console-wrapper {
  max-height: 100% !important;
}

请注意,您的原始代码在找到爱好匹配时并没有停止循环(如果爱好数组中有重复的条目,则会多次添加相同的成员 - 但可能并不意味着在该数组中重复)。

您也可以将String#localeComparesensitivity: "base" 选项一起使用,而不是比较小写字符串。

【讨论】:

  • 谢谢,这很好用!我了解本机函数将使用循环。我只是想使用它们而不是我自己的循环。 :)
  • 无关:今天我在评论低质量新手问题时提出了一个关于良好/有效/...“自动”消息的元问题 (meta.stackoverflow.com/questions/372795/…)。我收到的反馈几乎是“你在做完全错误的事情”。现在我只是想知道你怎么看这个?您的 quiver 中是否有“通用”消息,或者在这种情况下您是否只编写特定的 cmets?
  • @GhostCat - 我现在没有时间评论那些具体的文本,但我强烈不同意人们说“投反对票并继续前进”。我确实有一些精心制作的消息,但我确保每当我选择一个时,我都会根据具体情况对其进行调整(我可以在发布之前这样做)。如果他们有知情徽章,我不会告诉他们去参观。如果他们已经成为会员两年了,我不会说“欢迎来到 Stack Overflow”,但这只是他们的第三个问题。我的首要原则是:评论必须有用,并且必须欢迎。 (这……并不总是我的规则。)
【解决方案5】:

第一个解决方案:有点破解但是,嘿,没有循环

第二种解决方案:使用Array.findIndex 可能会减少内部循环中的迭代次数(嗯,至少给你一些概率更少的迭代)因为(MDN):

...如果找到这样的元素,findIndex 立即返回索引 对于那个迭代......

const findMembersWithValueForKey = (members, key, value) => 
  members.filter(member => member[key] instanceof Array
    && `#${member[key].join("#")}#`.toLowerCase()
         .indexOf(`#${value.toLowerCase()}#`) > -1
    || false);
    
const findMembersWithValueForKey2 = (members, key, value) => {
    value = value.toLowerCase();
    return members.filter(member => 
      member[key] instanceof Array
      && member[key].findIndex(v => v.toLowerCase() === value) > -1
      || false);
};
    
const members = [
  { name: "Sue", hobby: ["Swimming", "Running", "Dancing"] },
  { name: "Sam", hobby: ["Cars", "Travelling"] },
  { name: "John", hobby: ["Reading", "Swimming"] },
  { name: "Rob", hobby: ["Running", "Coding"] },      
];

console.log(findMembersWithValueForKey(members, "hobby", "swimming"));

console.log(findMembersWithValueForKey2(members, "hobby", "swimming"));

【讨论】:

  • filterindexOf 都是循环操作。不过,有趣的方法。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-27
  • 2019-12-16
  • 1970-01-01
  • 1970-01-01
  • 2014-01-10
  • 2021-11-16
相关资源
最近更新 更多