【问题标题】:JS: Compare values in Array of Objects and detect matching valuesJS:比较对象数组中的值并检测匹配值
【发布时间】:2020-10-13 11:22:23
【问题描述】:

我在 Javascript 中有一个对象数组,例如:

    var arrobj = [
  {'id': 1, 'editors': 'Andrew||Maria', 'authors': 'Dorian||Gabi', 'agents': 'Bob||Peter'},
  {'id': 2, 'editors': 'Dorian||Guybrush', 'author': 'Peter||Frodo', 'agents': 'Dorian||Otto'},
  {'id': 3, 'editors': 'Klaus||Otmar', 'authors': 'Jordan||Morgan', 'agents': 'Jordan||Peter'},
    ];

我需要列出每个对象中出现的所有人(编辑、作者和代理)及其角色。输出应该包含一个新的键/值对('involved'),如下所示:

'involved': 'Andrew (editor)|| Maria (editor)|| Dorian (author) || Gabi (author) || Bob (agent) || Peter (agent)'

对象数组应该是这样的:

   var arrobj = [
  {'id': 1, 'editors': 'Andrew||Maria', 'authors': 'Dorian||Gabi', 'agents': 'Bob||Peter', 'involved': 'Andrew (editor)|| Maria (editor)|| Dorian (author) || Gabi (author) || Bob (agent) || Peter (agent)'},
  {'id': 2, 'editors': 'Dorian||Guybrush', 'authors': 'Peter||Frodo', 'agents': 'Dorian||Otto','involved': 'Dorian (editor, agent) || Gybrush (editor) || Peter (author) || Frodo (author) || Otto (author)'},
  {'id': 3, 'editors': 'Klaus||Otmar', 'authors': 'Jordan||Morgan', 'agents': 'Jordan||Peter','involved': 'Klaus (editor) || Otmar (editor) || Jordan (author, agent) || Morgan (author) || Peter (agent)'},
    ];

如果一个人与多个角色相关联(例如,id 2 --> Dorian 出现在 editors 和 agent 中),他们在“involved”中的出现应该只有一次,但两个角色都在括号中(例如 Dorian (editor , 代理) )

我对编程很陌生,想不出正确的方法。 第一步,我想我必须用“||”分割所有值放入数组中,然后将每个名称与数组中的每个其他名称进行比较。

非常感谢您对我的问题的帮助。

【问题讨论】:

  • “第一步,我想我必须将所有值按“||”拆分为数组,然后将每个名称与数组中的每个其他名称进行比较。” 请将您尝试过的代码添加到问题中。
  • 所以你想在当前对象中包含一个键/值对,它具有几乎相同的信息,但在一个键/值对条目中?当可以通过遍历对象轻松访问数据时,我看不到复制数据的意义

标签: javascript arrays object string-comparison


【解决方案1】:

您需要收集所有姓名及其工作类型并返回分组结果。

 const
     getInvolved = o => {
         const
             jobs = ['editor', 'author', 'agent'],
             names = jobs.reduce((r, k) => {
                 (o[k + 's'] || '').split('||').forEach(v => (r[v] ??= []).push(k));
                 return r;
             }, {});

         return Object.entries(names).map(([k, v]) => `${k} (${v.join(', ')})`).join(' || ')
     },
     array = [{ id: 1, editors: 'Andrew||Maria', authors: 'Dorian||Gabi', agents: 'Bob||Peter' }, { id: 2, editors: 'Dorian||Guybrush', author: 'Peter||Frodo', agents: 'Dorian||Otto' }, { id: 3, editors: 'Klaus||Otmar', authors: 'Jordan||Morgan', agents: 'Jordan||Peter' }],
     result = array.map(o => ({ ...o, involved: getInvolved(o) }));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:
    • map数组和destructure每个对象得到一个roles没有id的对象。

    • 创建一个map 对象,它将每个人映射到他们的角色数组

    • 遍历roles 对象和split 中的每个键|| 以获取名称数组

    • 遍历名称并更新map 对象。如果尚未添加 name,请使用 ||= 赋值添加它

    • 使用slice删除角色的最后一个字符以将其从复数转换为单数(“agents”到“agent”)

    • map 对象现在将每个人作为键,将角色数组作为值。

      {
        Dorian: ["editor", "agent"],
        Guybrush: ["editor"],
        Peter: ["author"],
        Frodo: ["author"],
        Otto: ["agent"]
      }
      
    • 遍历对象的条目并创建involved 字符串

    • 返回一个带有额外 involved 键的新对象

    const arrobj = [
      {'id': 1, 'editors': 'Andrew||Maria', 'authors': 'Dorian||Gabi', 'agents': 'Bob||Peter'},
      {'id': 2, 'editors': 'Dorian||Guybrush', 'authors': 'Peter||Frodo', 'agents': 'Dorian||Otto'},
      {'id': 3, 'editors': 'Klaus||Otmar', 'authors': 'Jordan||Morgan', 'agents': 'Jordan||Peter'},
    ];
        
    const output = arrobj.map(({ id, ...roles }) => {
      const map = {}
      
      for (const r in roles) {
        const names = roles[r].split("||")
        for (const name of names) {
          map[name] ||= []
          map[name].push(r.slice(0,-1))
        }
      }
      
      const involved = Object.entries(map)
                             .map(([name, values]) => `${name} (${values.join(", ")})`)
                             .join(" || ")
                             
       return { id, ...roles, involved }
    })
    
    console.log(output)

    【讨论】:

      【解决方案3】:

      这是一个解决方案的示例(ES5),有一些优化可能。基本思路是推送所有编辑器,供作者和代理检查是否已经存在于之前组合的数组中。

      var arrobj = [
        {'id': 1, 'editors': 'Andrew||Maria', 'authors': 'Dorian||Gabi', 'agents': 'Bob||Peter'},
        {'id': 2, 'editors': 'Dorian||Guybrush', 'authors': 'Peter||Frodo', 'agents': 'Dorian||Otto'},
        {'id': 3, 'editors': 'Klaus||Otmar', 'authors': 'Jordan||Morgan', 'agents': 'Jordan||Peter'},
          ];
          
      function getInvolved(arr) {
        return arr.map(function(el) {
          var editors = el.editors.split('||');
          var authors = el.authors.split('||');
          var agents = el.agents.split('||'); 
          var involved = editors.map(function(editor) {
            return editor += ' (editor)';
          });
          
          authors.forEach(function(author) { 
            if(editors.indexOf(author) === -1) {
              involved.push(author + ' (author)');
            } else {
              involved = involved.map(function(inv) {
                if(inv.indexOf(author) > -1) {
                  inv += '(author)';
                }
                return inv;
              });
            }
          });
          
          agents.forEach(function(agent) { 
            if(editors.indexOf(agent) === -1 && authors.indexOf(agent) === -1) {
              involved.push(agent + ' (agent)');
            } else {
              involved = involved.map(function(inv) {
                if(inv.indexOf(agent) > -1) {
                  inv += '(agent)';
                }
                return inv;
              });
            }
          });
          el.involved = involved.join('||'); 
          return el;
        });
      }
      
      console.log(getInvolved(arrobj));

      【讨论】:

        【解决方案4】:

        const arrobj = [
          {'id': 1, 'editors': 'Andrew||Maria', 'authors': 'Dorian||Gabi', 'agents': 'Bob||Peter'},
          {'id': 2, 'editors': 'Dorian||Guybrush', 'authors': 'Peter||Frodo', 'agents': 'Dorian||Otto'},
          {'id': 3, 'editors': 'Klaus||Otmar', 'authors': 'Jordan||Morgan', 'agents': 'Jordan||Peter'},
        ];
        
        for (let obj of arrobj) {
          obj.involved = "";
          for (let key of Object.keys(obj)) {
            let strKey = [...key];
            strKey.pop();
            let role = strKey.join("");
            if (key === "involved") break;
            if (key !== "id") {
              obj.involved += obj[key]
                .split("||")
                .map((name) => name + "(" + role + ")||")
                .join("");
            }
            obj.involved = obj.involved.substr(0, obj.involved.length - 2).trim();
          }
        }
        
        console.log(arrobj);

        这是正在运行的repl:https://repl.it/join/juljqzxt-theketan2

        【讨论】:

        • 输出不正确。如果一个人有多个角色,他们希望将其分组为:Dorian (editor, agent)
        • 我没想到,但这很容易实现。感谢您的提醒?
        猜你喜欢
        • 1970-01-01
        • 2022-01-02
        • 1970-01-01
        • 1970-01-01
        • 2023-03-10
        • 1970-01-01
        • 1970-01-01
        • 2021-02-04
        • 2014-11-06
        相关资源
        最近更新 更多