【问题标题】:How can I refactor my code to Javascript ES6 using map or filter?如何使用映射或过滤器将我的代码重构为 Javascript ES6?
【发布时间】:2019-08-01 20:10:21
【问题描述】:

此函数将一组驱动程序对象作为第一个参数,并使用一个 JavaScript 对象指定属性和相应的值。 例如,exactMatch(drivers, { revenue: 3000 }) 将返回所有收入属性等于 3000 的司机,exactMatch(drivers, { name: 'Bob' }) 将返回所有姓名属性等于 Bob 的司机。

我尝试使用地图和过滤器进行设置,但没有成功。我尝试使用带有映射或过滤器的 ES6 格式重写此代码,或者只是重构以获得更好的代码。任何帮助,将不胜感激!总的来说,我对编程和 JS 非常陌生。

function exactMatch(drivers, obj){
  const driverMatch = [];
  for (const driver of drivers){
    for (const key in obj){
      if (driver[key] === obj[key]){
        driverMatch.push(driver);
      }
    }
  }
  return driverMatch;
}

重构以获得更好的代码并使用 JS ES6。

【问题讨论】:

  • mapfilter 不是 ES6 - 它们在 ES5 中可用。
  • obj 中是否只有一个键/值或更多,然后会发生什么?应该所有属性匹配还是只匹配一个?
  • 我应该更具体一些 - 希望将箭头功能与地图或过滤器一起使用。
  • @AlisonGolden 使用 .map.filter 与普通函数和使用箭头函数之间(几乎)没有区别。他们是interchangeable unless with some caveats。但是对于这种情况,这些都不适用。
  • 根据实验室测试,它在 obj 中只有一个键/值对被传入。

标签: javascript


【解决方案1】:

我会从第二个参数生成一个谓词。由于它包含一个键和一个值,因此Object.entries 会将其分解为这些,您可以从中生成一个谓词,该谓词只需在每个键值对上运行Array#every 以检查对象是否与其中的每一个匹配:

const makePredicate = template => {
  const keyValues = Object.entries(template);
  
  return obj => keyValues.every(([key, value]) => obj[key] === value)
}

const predicate = makePredicate({name: "Bob"});

const a = {name: "Alice"};
const b = {name: "Bob"};

console.log(predicate(a));
console.log(predicate(b));

所以你可以在之后直接在Array#filter 中使用这个谓词:

const makePredicate = template => {
  const keyValues = Object.entries(template);

  return obj => keyValues.every(([key, value]) => obj[key] === value)
}
const drivers = [{
    name: "Alice",
    revenue: 20000,
    colour: "red"
  },
  {
    name: "Bob",
    revenue: 10000,
    colour: "blue"
  },
  {
    name: "Carol",
    revenue: 10000,
    colour: "red"
  }
]

console.log(drivers.filter(makePredicate({
  name: "Bob"
})));

console.log(drivers.filter(makePredicate({
  revenue: 10000,
  colour: "red"
})));

如果您只想匹配提供的至少一个键值,那么您可以交换并使用Array#some

const makePredicate = template => {
  const keyValues = Object.entries(template);

  return obj => keyValues.some(([key, value]) => obj[key] === value)
  //                      ^^^^
}
const drivers = [{
    name: "Alice",
    revenue: 20000,
    colour: "red"
  },
  {
    name: "Bob",
    revenue: 10000,
    colour: "blue"
  },
  {
    name: "Carol",
    revenue: 10000,
    colour: "red"
  }
]

console.log(drivers.filter(makePredicate({
  name: "Bob"
})));

console.log(drivers.filter(makePredicate({
  revenue: 10000,
  colour: "red"
})));

【讨论】:

    【解决方案2】:

    简答:

    function exactMatch(drivers, obj) {
      return drivers.filter(driver => {
        const truths = Object.keys(obj).map(k => driver[k] === obj[k])
        return truths.filter(Boolean).length === truths.length
      })
    }
    

    有几种方法可以做到这一点,但这是我想到的第一种方法。这是假设您可以传递像 { name: 'Bob', salary: 20000 } 这样的 obj 并要求这两个条件都为真。

    【讨论】:

    • 这个答案正是我一直在寻找的......简单而干净,而且很有效!你能解释一下为什么使用(Boolean)吗?我对此有点困惑。
    • 没关系..我了解用于过滤和返回匹配案例的布尔值。我还专门寻找一个关于如何正确使用 Object.keys 的解决方案,这清楚地为我定义了它。谢谢!
    【解决方案3】:

    您可以提前获取obj 的条目并过滤数组并检查Array#some,如果一个键/值对匹配。

    // one property match
    function exactMatch(drivers, obj) {
        var entries = Object.entries(obj);
        return drivers.filter(driver => entries.some(([k, v]) => driver[k] === v));
    }
    

    对于所有应该匹配的属性,您可以选择Array#every

    // all properties have to match
    function exactMatch(drivers, obj) {
        var entries = Object.entries(obj);
        return drivers.filter(driver => entries.every(([k, v]) => driver[k] === v));
    }
    

    【讨论】:

    • 我还没有使用过 Array#some 或 Array#every 但我喜欢这个解决方案。谢谢!
    【解决方案4】:

    const exampleData = {
      drivers: [
        {
          name: 'Bob',
          revenue: 5000,
        },
        {
          name: 'Alice',
          revenue: 3000
        },
        {
          name: 'Allen',
          revenue: 4000
        },
        {
          name: 'Monkey',
          revenue: 5000
        }
      ]
    };
    
    // Finds the first occurance
    function exactMatch(exampleData, target) {
      const targetKey = Object.keys(target)[0]
      const targetValue = Object.values(target)[0]
      return exampleData.drivers.find(driver => driver[targetKey] === targetValue)
    }
    
    // Finds all of the data that met the condition
    
    function matchAll(exampleData, target) {
      const targetKey = Object.keys(target)[0]
      const targetValue = Object.values(target)[0]
      return exampleData.drivers.filter(driver => driver[targetKey] === targetValue)
    }
    
    const resultA = exactMatch(exampleData, {revenue: 4000})
    console.log(resultA)
    
    const resultB = matchAll(exampleData, {revenue: 5000})
    console.log(resultB)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-06
      • 1970-01-01
      • 2015-12-22
      • 2019-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多