【问题标题】:Looking for a way in Javascript to convert a column style array with duplicate data into an object在 Javascript 中寻找一种将具有重复数据的列样式数组转换为对象的方法
【发布时间】:2019-05-20 06:10:39
【问题描述】:

我正在尝试将一个如下所示的数组转换为该数组下方对象的结构。

我已经尝试了很多东西,我也会在下面列出。但我觉得我走错了路。在这方面需要一些帮助。

var array = [
  ["plan_a", "tester_a", "product", "foo", "blocked", "5"],
  ["plan_a", "tester_a", "product", "foo", "passed", "10"],
  ["plan_a", "tester_a", "subproduct", "client", "passed", "15"],
  ["plan_a", "tester_b", "product", "bar", "blocked", "5"],
  ["plan_a", "tester_b", "product", "bar", "passed", "10"],
  ["plan_a", "tester_b", "subproduct", "server", "failed", "5"],
  ["plan_a", "tester_b", "subproduct", "server", "passed", "5"],
  ["plan_a", "tester_c", "product", "foo", "failed", "5"]
];

var object = {
  plan_a: {
    tester_a: {
      product: {
        product: "foo",
        blocked: "5",
        passed: "10"
      },
      subproduct: {
        subproduct: "client",
        passed: "15"
      }
    },
    tester_b: {
      product: {
        product: "bar",
        blocked: "5",
        passed: "10"
      },
      subproduct: {
        subproduct: "server",
        failed: "5",
        passed: "5"
      }
    },
    tester_c: {
      product: {
        product: "foo",
        failed: "5"
      }
    }
  }
};

我试过这个:

var object = {}
var combining_plans =[]
var first_row = arr[0][0];

for (var i = 0; i < arr.length; i++) {
    if (arr[i][0] == first_row) {
        object[arr[i][0]] = [];
        arr[i].shift();
        combining_plans.push(arr[i]);
    }
}

object[first_row] = combining_plans;

这会检查第一列是否相同,如果它采用第一个元素将其转换为对象的第一个键,然后将值添加为数组的所有剩余元素。

我一直在考虑对每一列都这样做,但我觉得这可能行不通,还有比这样做更优雅的方法。

【问题讨论】:

    标签: javascript arrays json ecmascript-6 javascript-objects


    【解决方案1】:

    const array = [
    	["plan_a", "tester_a", "product"   ,"foo"   ,"blocked", "5"  ],
    	["plan_a", "tester_a", "product"   ,"foo"   ,"passed" , "10" ],
    	["plan_a", "tester_a", "subproduct","client","passed" , "15" ],
    	["plan_a", "tester_b", "product"   ,"bar"   ,"blocked", "5"  ],
    	["plan_a", "tester_b", "product"   ,"bar"   ,"passed" , "10" ],
    	["plan_a", "tester_b", "subproduct","server","failed" , "5"  ],
    	["plan_a", "tester_b", "subproduct","server","passed" , "5"  ],
    	["plan_a", "tester_c", "product"   ,"foo"   ,"failed" , "5"  ],
    ];
    const result = {};
    array.forEach((item) => {
    	const [plan, tester, type, name, key, value] = item;
    	if(!result[plan]) {
    		result[plan] = {};
    	}
    	if(!result[plan][tester]) {
    		result[plan][tester] = {};
    	}
    	if(!result[plan][tester][type]) {
    		result[plan][tester][type] = {[type]: name};
    	}
    	Object.assign(result[plan][tester][type], {[key]: value});
    });
    console.log(result);

    【讨论】:

      【解决方案2】:

      您可以使用Array.reduce()Array.forEach() 创建对象:

      const array = [
        ["plan_a", "tester_a", "product"   ,"foo"   ,"blocked", "5"   ],
        ["plan_a", "tester_a", "product"   ,"foo"   ,"passed" , "10"  ],
        ["plan_a", "tester_a", "subproduct","client","passed" , "15"  ],
        ["plan_a", "tester_b", "product"   ,"bar"   ,"blocked", "5"   ],
        ["plan_a", "tester_b", "product"   ,"bar"   ,"passed" , "10"  ],
        ["plan_a", "tester_b", "subproduct","server","failed" , "5"  ],
        ["plan_a", "tester_b", "subproduct","server","passed" , "5"  ],
        ["plan_a", "tester_c", "product"   ,"foo"   ,"failed" , "5"  ],
      ];
      
      const result = array.reduce((r, row) => {
        const val = row[row.length - 1];
        const path = row.slice(0, -1);
        let current = r;
        
        path.forEach((p, i) => {
          if(i === 4) current[p] = val;
          else if(i === 3) current[path[2]] = p;
          else {
            current[p] = current[p] || {};
            current = current[p];
          }
        });
        
      
        return r;
      }, {});
      
      console.log(result);

      【讨论】:

        【解决方案3】:

        提供答案的替代方法是 map+reduce。

        您可以将数组映射到类似结果的形状的对象块中,之后可以进行深度合并:

        const array = [
          ["plan_a", "tester_a", "product", "foo", "blocked", "5"],
          ["plan_a", "tester_a", "product", "foo", "passed", "10"],
          ["plan_a", "tester_a", "subproduct", "client", "passed", "15"],
          ["plan_a", "tester_b", "product", "bar", "blocked", "5"],
          ["plan_a", "tester_b", "product", "bar", "passed", "10"],
          ["plan_a", "tester_b", "subproduct", "server", "failed", "5"],
          ["plan_a", "tester_b", "subproduct", "server", "passed", "5"],
          ["plan_a", "tester_c", "product", "foo", "failed", "5"]
        ];
        
        
        const result = array.map(mapIntoResultChunkShape).reduce(merge);
        //                                                       ^^^^^ comes from lodash
        
        function mapIntoResultChunkShape([
          product,
          tester,
          categoryName,
          categoryValue,
          resultName,
          resultValue
        ]) {
          return {
            [product]: {
              [tester]: {
                [categoryName]: {
                  [categoryName]: categoryValue,
                  [resultName]: resultValue
                }
              }
            }
          };
        }
        
        console.log(JSON.stringify(result, null, 2));
        &lt;script src="https://unpkg.com/lodash.merge@4.6.1/index.js"&gt;&lt;/script&gt;

        这种方法的主要好处是它可以解耦关注点。要将此代码调整为任何其他数组->对象转换,您需要做的就是更改数组项映射到结果形状的方式,即mapIntoResultChunkShape 函数。

        您还可以为您的用例专门构建自己的合并函数,与使用为处理所有情况而构建的更通用的库相比,它的开销更少:

        const array = [
          ["plan_a", "tester_a", "product", "foo", "blocked", "5"],
          ["plan_a", "tester_a", "product", "foo", "passed", "10"],
          ["plan_a", "tester_a", "subproduct", "client", "passed", "15"],
          ["plan_a", "tester_b", "product", "bar", "blocked", "5"],
          ["plan_a", "tester_b", "product", "bar", "passed", "10"],
          ["plan_a", "tester_b", "subproduct", "server", "failed", "5"],
          ["plan_a", "tester_b", "subproduct", "server", "passed", "5"],
          ["plan_a", "tester_c", "product", "foo", "failed", "5"]
        ];
        
        const result = array.map(mapIntoResultChunkShape).reduce(mergeResultChunkShapes);
        
        function mapIntoResultChunkShape([
          product,
          tester,
          categoryName,
          categoryValue,
          resultName,
          resultValue
        ]) {
          return {
            [product]: {
              [tester]: {
                [categoryName]: {
                  [categoryName]: categoryValue,
                  [resultName]: resultValue
                }
              }
            }
          };
        }
        
        function mergeResultChunkShapes(item1, item2) {
          if (
            item1 === null ||
            typeof item1 !== "object" ||
            (item2 === null || typeof item2 !== "object")
          ) {
            return item1 || item2;
          }
        
          const uniqueKeys = new Set(Object.keys(item1).concat(Object.keys(item2)));
        
          return Array.from(uniqueKeys).reduce((res, key) => {
            return Object.assign(res, {
              [key]: mergeResultChunkShapes(item1[key], item2[key])
            });
          }, {});
        }
        
        console.log(JSON.stringify(result, null, 2));

        【讨论】:

          猜你喜欢
          • 2016-07-03
          • 2022-12-05
          • 2015-05-14
          • 2021-10-24
          • 1970-01-01
          • 2021-04-27
          • 2021-11-03
          • 2021-04-23
          • 1970-01-01
          相关资源
          最近更新 更多