【问题标题】:Match an array with an object property将数组与对象属性匹配
【发布时间】:2021-06-02 22:42:42
【问题描述】:

我有一个具有如下属性的对象:

{
  maj6: { chromatic: [ 0, 4, 7, 9 ] },
  min6: { chromatic: [ 0, 3, 7, 9 ] },
  maj7: { chromatic: [ 0, 4, 7, 11 ] },
  min7: { chromatic: [ 0, 3, 7, 10 ] },
  minmaj7: { chromatic: [ 0, 3, 7, 11 ] },
  dom7: { chromatic: [ 0, 4, 7, 10 ] },
  maj9: { chromatic: [ 0, 4, 7, 11, 14 ] },
  dom9: { chromatic: [ 0, 4, 7, 10, 14 ] },
  maj: { chromatic: [ 0, 4, 7 ] },
  min: { chromatic: [ 0, 3, 7 ] },
  aug: { chromatic: [ 0, 4, 8 ] },
  dim: { chromatic: [ 0, 3, 6 ] }
}

我正在计算一个数组,例如 [0,4,7],我试图将其与上述对象属性之一匹配。我正在尝试使用 find 函数来实现这一点,如以下代码 sn-p 所示:

  matchParsedToChord() {
    const result = this.blocks //returns larger payload
    .map(block => block.chromatic) // returns array [0,4,7,4,7,7,7,4]
    .filter((v,i,arr) => arr.indexOf(v) === i) //removes redundancies  [0,4,7]
    .find(v => { //attempts to 
      v === Object.keys(chordDefinitions).map(key => chordDefinitions[key].chromatic)
    })
    console.log(result)
  }

我的问题是 Object.keys 逻辑返回整个数组,而我想逐个元素进行比较。

我想返回数组关联的对象属性,例如:

maj: { chromatic: [ 0, 4, 7 ] }

非常感谢

【问题讨论】:

  • 您的预期结果是什么?
  • 你看过lodash吗? _.findKey 函数可能正是您想要的。
  • @Nakul - 这些解决方案是否解决了您的问题?如果是这样,请接受答案。如果没有,请回复为什么不这样我们可以提供帮助。干杯。

标签: javascript object find higher-order-functions


【解决方案1】:

这将返回具有您正在寻找的模式的所有和弦。它只是将数组展平并查找 indexOf 来组装所有匹配项。可以严格(完全匹配)或包含(所有部分匹配)运行它

const a = {
  maj6: { chromatic: [ 0, 4, 7, 9 ] },
  min6: { chromatic: [ 0, 3, 7, 9 ] },
  maj7: { chromatic: [ 0, 4, 7, 11 ] },
  min7: { chromatic: [ 0, 3, 7, 10 ] },
  minmaj7: { chromatic: [ 0, 3, 7, 11 ] },
  dom7: { chromatic: [ 0, 4, 7, 10 ] },
  maj9: { chromatic: [ 0, 4, 7, 11, 14 ] },
  dom9: { chromatic: [ 0, 4, 7, 10, 14 ] },
  maj: { chromatic: [ 0, 4, 7 ] },
  min: { chromatic: [ 0, 3, 7 ] },
  aug: { chromatic: [ 0, 4, 8 ] },
  dim: { chromatic: [ 0, 3, 6 ] }
}

function getPattern(pattern, strict) {
  let b = []
  for (const [key, value] of Object.entries(a)) {
   let set = Object.values(value).flat().join(",") ;
    if ((!strict && set.indexOf(pattern) !== -1) || (strict && set == pattern)) b.push({
      [key]: value
    })
  }
  if (strict && b.length>0) b = b[0];
  return b;
}

// Contains (partial matches)
let matches = getPattern("0,4,7", false);
console.log('Contains', matches);

// strict
matches = getPattern("0,4,7", true);
console.log('Strict', matches);

【讨论】:

    【解决方案2】:

    使用 Array#every() 并匹配长度。目前还不清楚您正在寻找什么结果,因此这可能需要根据您的期望进行修改

    const data ={
      maj6: { chromatic: [ 0, 4, 7, 9 ] },
      min6: { chromatic: [ 0, 3, 7, 9 ] },
      maj7: { chromatic: [ 0, 4, 7, 11 ] },
      min7: { chromatic: [ 0, 3, 7, 10 ] },
      minmaj7: { chromatic: [ 0, 3, 7, 11 ] },
      dom7: { chromatic: [ 0, 4, 7, 10 ] },
      maj9: { chromatic: [ 0, 4, 7, 11, 14 ] },
      dom9: { chromatic: [ 0, 4, 7, 10, 14 ] },
      maj: { chromatic: [ 0, 4, 7 ] },
      min: { chromatic: [ 0, 3, 7 ] },
      aug: { chromatic: [ 0, 4, 8 ] },
      dim: { chromatic: [ 0, 3, 6 ] }
    }
    
    const arr =  [0,4,7];
    
    const entries = Object.entries(data).map(([k,v])=> [k, [...new Set(v.chromatic)]]);
    
    const match = entries.find(([k,v])=> v.length === arr.length && arr.every(n => v.includes(n)))
    
    console.log(match)

    【讨论】:

      【解决方案3】:

      您不应该在从this.blocks 获得的数组上使用find()。这只会返回一个数字,例如 3

      我假设您想返回与整个数组匹配的 chordDefinitions 中的条目。所以你应该将该数组放入一个变量中,然后在chordDefinitions 中搜索相等的chromatic 属性。

      我已将其转换为 Set 以删除重复项并提高搜索效率。

      function matchParsedToChord() {
        const chord = new Set(
          this.blocks //returns larger payload
          .map(block => block.chromatic) // returns array [0,4,7,4,7,7,7,4]
        ); // Converting to Set removes duplicates
        const chordSize = thisChord.size;
        const result = Object.entries(chordDefinitions)
          .find(([name, val]) => val.chromatic.length == chordSize && val.chromatic.every(v => chord.has(v)));
        console.log(result)
      }

      【讨论】:

        【解决方案4】:

        你的意思是这样的吗? 编辑为使用 reduce 来获得所需的回报

        const a = {
          maj6: { chromatic: [ 0, 4, 7, 9 ] },
          min6: { chromatic: [ 0, 3, 7, 9 ] },
          maj7: { chromatic: [ 0, 4, 7, 11 ] },
          min7: { chromatic: [ 0, 3, 7, 10 ] },
          minmaj7: { chromatic: [ 0, 3, 7, 11 ] },
          dom7: { chromatic: [ 0, 4, 7, 10 ] },
          maj9: { chromatic: [ 0, 4, 7, 11, 14 ] },
          dom9: { chromatic: [ 0, 4, 7, 10, 14 ] },
          maj: { chromatic: [ 0, 4, 7 ] },
          min: { chromatic: [ 0, 3, 7 ] },
          aug: { chromatic: [ 0, 4, 8 ] },
          dim: { chromatic: [ 0, 3, 6 ] }
        }
        
        const find = (obj, match = [0,4,7]) => {
          return Object.keys(a)
          .reduce((acc, k) => {
            // If you want more loose match, just switch search direction
            // like: match.every(m => obj[k].chromatic.includes(m)
            if(obj[k].chromatic.every(m =>  match.includes(m))) {
              acc[k] = obj[k];
            }
            return acc;
          },
          {})
        }
        console.log(find(a))

        【讨论】:

          猜你喜欢
          • 2018-05-07
          • 2022-09-23
          • 1970-01-01
          • 2020-06-20
          • 1970-01-01
          • 2022-11-21
          • 2019-05-25
          • 2016-04-07
          • 2019-02-28
          相关资源
          最近更新 更多