【问题标题】:How to remap an Array of object to be Object of Object in Javascript如何在Javascript中将对象数组重新映射为对象对象
【发布时间】:2020-12-08 17:19:35
【问题描述】:

我有这个值:

const sample = [{

  name: "name",
  value1: 1,
  mean: 2,
  create: 10,

  age: "age",
  player1: 20,
  player2: 40,

  sample: "sample",
  player3: 30,
  player4: 100,
}];

要映射到:

{
  name: {
    value: 1,
    mean: 2,
    create: 10
  },
  age: {
    player1: 20,
    player2: 40
  },
  sample: {
    player3: 30,
    player4: 100
  }
}

我知道我可以做的是手动映射它,但我的列表大约是 50,所以这是不可能的。

编辑:

关键属性是字符串,数字是该顺序中的值

【问题讨论】:

  • 你知道哪些属性属于name,哪些属于age,目前是硬编码列表
  • 关键属性是字符串,数字是值
  • 不,我的意思是 player1player2 被固定为正确的年龄,你知道什么会映射到它
  • @ajbee ...但您知道您实际上依赖于一个始终必须确保例如的结构Object.keys 将完全按照创建/分配的顺序显示键。并且创建此类对象的环境也必须确保这种可行且可重现的顺序。
  • 我刚刚看到你的编辑,实际上,你不能在一个对象中有两个属性具有相同的键,所以在你的例子中,你不能有多个 player1player2 与不同的值 - player1 的第二个值将替换第一个值。

标签: javascript arrays data-structures mapping


【解决方案1】:

您的描述不清楚,但是,我认为您想将一组属性重新映射为一个新属性,前提是键和值相同。

此外,我放了一个新的 key = value = "other",之后的属性被分组在 "other" 下,所以你不必指定所有的键...

const sample = [{
  name: "name",
  value1: 1,
  mean: 2,
  create: 10,

  age: "age",
  player1: 20,
  player2: 40,
}, {
  name: "name",
  value1: 1,
  mean: 2,
  create: 10,

  age: "age",
  player1: 20,
  player2: 40,

  other: "other",
  p2: "ldkdskd",
  p1: 10
}];
    
function remapdata(data) {
  const obj = {};
  const keys = Object.keys(data);
  let lastGroup = undefined;
  let i = 0;`enter code here`
  while(i < keys.length) {
    if(keys[i] === data[keys[i]]) {
      obj[keys[i]]= {};
      lastGroup=keys[i];  
    } else if (lastGroup) {
      obj[lastGroup][keys[i]] = data[keys[i]];
    }
    i++;
  } 
  return obj;
}
const mapped = sample.map(remapdata);

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

【讨论】:

    【解决方案2】:

    每个人都应该知道,任何将重构任何对象的键值对的方法实际上都依赖于始终必须确保的结构,例如Object.keys,一个完全代表任何键创建顺序的键顺序。此外,创建此类对象的环境也必须确保这种可行且可重现的顺序。

    如果可以概括," ... 每当在键值对中 key 等于 value 时,人们想通过 key 创建一个分配给重采样结构的新对象。",应该按原样使用下面提供的方法。否则,必须将负责创建新子结构的条件限制为任何 string 类型value,这也确实限制了原始结构允许具有的类型。 ...

    const sampleList = [{
      name: "name",
      value1: 1,
      mean: 2,
      create: 10,
    
      age: "age",
      player1: 20,
      player2: 40,
    
      sample: "sample",
      player3: 30,
      player4: 100
    }, {
      sample: "sample",
      player1: 130,
      player2: 1100,
    
      name: "name",
      value1: 11,
      mean: 12,
      create: 110,
    
      age: "age",
      player3: 120,
      player4: 140
    }];
    
    
    function restructureSample(sample) {
      const newSample = {};
      return Object.entries(sample).reduce((reference, tuple, idx, arr) => {
    
        const [key, value] = tuple;
      //if (typeof value === 'string') {  // - more generic, but limiting the use cases.
        if (key === value) {              // - maybe even more precise.
    
          reference = newSample[key] = {};
        } else {
          reference[key] = value;
        }
        return (((idx === (arr.length - 1)) && newSample) || reference);
    
      }, newSample);
    }
    
    
    console.log(sampleList.map(restructureSample));
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    【讨论】:

      【解决方案3】:

      使用Array#map 将其映射到内部的新对象结构。

      const sample = [
       {
        name: "name",
        value1: 1,
        mean: 2,
        create: 10,
        age: "age",
        player1: 20,
        player2: 40,
       }
      ];
      
      let result = sample.map(elem => ({
          any : {
              name: {
                 value: elem.value1,
                 mean: elem.mean,
                 create: elem.create
              },
              age: {
                 player1: elem.player1,
                 player2: elem.player2
              }
         }
      }))
      
      console.log(result);

      【讨论】:

        【解决方案4】:

        要以正确的方式执行此操作,您需要在最终对象中指定属于nameage 的属性,如下例所示:

        const sample = [
          {
            name: "name",
            value1: 1,
            mean: 2,
            create: 10,
            age: "age",
            player1: 20,
            player2: 40
          },
          {
            name: "fred",
            value1: 3,
            mean: 5,
            create: 101,
            age: "age",
            player1: 202,
            player2: 401
          }
        ];
        
        
        const keyValuesMap = {
          // `name` property will have `value1`, `mean`, and `create` properties
          name: ["value1", "mean", "create"],
          
          // `age` property will have `player1` and `player2` properties
          age: ["player1", "player2"]
        };
        
        const result = sample.map((item) => {
          // map over the `sample` data and get the key/value pairs of each
          // item, then use `reduce` to create a new object based on the
          // `keyValuesMap` specified above
          return Object.entries(item).reduce((accumulator, [key, value]) => {
            const name = accumulator.name || {};
            const age = accumulator.age || {};
        
            // if value belongs to the `name` property, add to it
            if (keyValuesMap.name.includes(key)) {
              name[key] = value;
            }
            // if value belongs to the `age` property, add to it
            if (keyValuesMap.age.includes(key)) {
              age[key] = value;
            }
        
            accumulator.name = name;
            accumulator.age = age;
        
            return accumulator;
          }, {});
        });
        
        console.log("result", result);

        参考资料:

        【讨论】:

          【解决方案5】:

          你可能想要这样的东西

          const sample = [ { name: "name", value1: 1, mean: 2, create: 10, age: "age", player1: 20, player2: 40, }, ];
          
          res = sample.reduce((r, c) => {
            let key;
            Object.entries(c).forEach((o) => {
          (k = o[0]), (v = o[1]);
          typeof v == "string" ? ((key = v), (r[v] = {})) : (r[key][k] = v);
            });
            return r;
          }, {});
          console.log(res);

          【讨论】:

            【解决方案6】:

            使用Array.prototype.reduce 将数组和remap 现有属性缩减为您想要的格式。

            const sample = [
             {
              name: "name",
              value1: 1,
              mean: 2,
              create: 10,
              age: "age",
              player1: 20,
              player2: 40,
             }
            ];
            
            const result = sample.reduce((acc, { value1, mean, create, player1, player2 }) => {
                acc.push({
                    name: {
                        value1,
                        mean,
                        create
                    },
                    age: {
                        player1,
                        player2
                    }
                });
                return acc;
            }, []);
            
            console.log(result);

            对于动态键,您可以执行以下操作 -

            const sample = [
             {
              name: "name",
              value1: 1,
              mean: 2,
              create: 10,
              age: "age",
              player1: 20,
              player2: 40,
             }
            ];
            
            const keyMapping = {
                name: ['value1', 'mean', 'create'],
                age: ['player1', 'player2']
            };
            
            const result = sample.reduce((acc, curr) => {
                const obj = Object.entries(keyMapping).reduce((accumulator, [key, val]) => {
                    accumulator[key] = val.reduce((r, c) => {
                        r[c] = curr[c];
                        return r;
                    }, Object.create(null));
                    return accumulator;
                }, Object.create(null));
                
                acc.push(obj);
                return acc;
            }, []);
            
            console.log(result);

            【讨论】:

            • @ajbee ...那么您需要更具体。例如,如果样本结构不像 Q 中所示的那样固定,它会是什么样子,在这些情况下预期的结果是什么。
            【解决方案7】:

            您可以使用.map 函数迭代对象,并跟踪最后一个key 以向它们添加整数属性:

            const sample = [
             {
              name: "name",
              value1: 1,
              mean: 2,
              create: 10,
              age: "age",
              player1: 20,
              player2: 40,
              sample: "sample",
              player1a: 30,
              player2a: 100,
             },
             {
              name: "name",
              value1: 11,
              mean: 22,
              create: 130,
              age: "age",
              player1: 210,
              player2: 430,
              sample: "sample",
              player1a: 340,
              player2a: 1100,
             },
             {
              name: "name",
              value: 313,
              mean: 421,
              create: 23,
              age: "age",
              player1a: 440,
              player2a: 40,
             }
            ];
            let lastKey = null;
            let mapped = sample.map(elem => {
                 let obj = { any: {} };
                 let any = obj.any;
                 for(var p in elem){
                      let key = p, value = elem[p];
                      if(typeof(value)=="string"){
                           any[key] = {};
                           lastKey = key;
                      }else if(typeof(value)=="number"){
                           if(lastKey)
                                any[lastKey][key] = value;
                           else
                                any[key] = value;
                      }
                 }
                 return obj;
            });
            console.log(mapped);

            请注意,您不能拥有两个相同的密钥(player1player2),因为它应该是唯一的。

            【讨论】:

            • 为什么人们反对这个?
            • 这导致另一个数组
            猜你喜欢
            • 2020-09-18
            • 1970-01-01
            • 2022-11-24
            • 2020-06-23
            • 1970-01-01
            • 2022-06-17
            • 1970-01-01
            • 2020-11-09
            • 1970-01-01
            相关资源
            最近更新 更多