根据对象的属性将对象数组转换为哈希

时间:2019-05-19 20:14:31

标签: javascript arrays json

根据数组中JSON对象的键将JSON数组转换为地图

我正在尝试根据数组中JSON元素的属性将JSON数组转换为地图。

这是JSON数组的结构:

[
{"property1": "x","property2": "value1","property3": "value1"},
{"property1": "x","property2": "value2","property3": "value2"},
{"property1": "y","property2": "value3","property3": "value3"},
{"property1": "y","property2": "value4","property3": "value4"}
]

我想将JSON数组拆分成这样的映射:

{
"x": [{"property2": "value1","property3": "value1"}, 
       {"property2": "value2","property3": "value2"}],

"y": [{"property2": "value3","property3": "value3"},
      {"property2": "value4","property3": "value4"}]
}

我该如何使用Javascript?

(PS:我是Java的新手)

5 个答案:

答案 0 :(得分:2)

JavaScript的地图有Map,因此您可以这样做:

const data = [{"property1": "x","property2": "value1","property3": "value1"},{"property1": "x","property2": "value2","property3": "value2"},{"property1": "y","property2": "value3","property3": "value3"},{"property1": "y","property2": "value4","property3": "value4"}];

const map = new Map(data.map(o => [o.property1, []]));
data.forEach(({property1, ...rest}) => map.get(property1).push(rest));
const result = Object.fromEntries(map);

console.log(result);

如果您不喜欢使用Maps,最后一次分配会将Map转换为普通对象。

ES5

Map,箭头功能,对象文字扩展语法等在ES5中不可用。在该版本的JavaScript中,您可以执行以下操作:

const data = [{"property1": "x","property2": "value1","property3": "value1"},{"property1": "x","property2": "value2","property3": "value2"},{"property1": "y","property2": "value3","property3": "value3"},{"property1": "y","property2": "value4","property3": "value4"}];

var map = {}
data.forEach(function (o) {
    var cpy = Object.assign({}, o);
    delete cpy.property1;
    map[o.property1] = (map[o.property1] || []).concat(cpy);
});

console.log(map);

答案 1 :(得分:0)

尝试以下代码:

let a = [{
    "property1": "x",
    "property2": "value1",
    "property3": "value1"
  },
  {
    "property1": "x",
    "property2": "value2",
    "property3": "value2"
  },
  {
    "property1": "y",
    "property2": "value3",
    "property3": "value3"
  },
  {
    "property1": "y",
    "property2": "value4",
    "property3": "value4"
  }
];
let b = {};
for (o of a) {
  b[o.property1] = b[o.property1] || [];
  b[o.property1].push({
    property2: o.property2,
    property3: o.property3
  });
}
console.log(b);

此代码的作用是,首先为每个array创建一个property1属性(如果尚不存在)。然后,它仅使用property2property3将新对象推送到该数组中。

答案 2 :(得分:0)

对于功能性方法,您可以使用Object.values

var o = [
{"property1": "x","property2": "value1","property3": "value1"},
{"property1": "x","property2": "value2","property3": "value2"},
{"property1": "y","property2": "value3","property3": "value3"},
{"property1": "y","property2": "value4","property3": "value4"}
]

var r = Object.values(o).reduce((ac, x) => ({
    ...ac,
    [x.property1]: [
       ...(ac[x.property1] || []),
       x
    ]
}), {})

console.log(r)

答案 3 :(得分:0)

您可以通过Array.reduce获取此信息,然后确定是要使用对象文字还是Map开头:

使用地图:

let data = [{ "property1": "x", "property2": "value1", "property3": "value1" }, { "property1": "x", "property2": "value2", "property3": "value2" }, { "property1": "y", "property2": "value3", "property3": "value3" }, { "property1": "y", "property2": "value4", "property3": "value4" } ]

let result = data.reduce((r,{property1, property2, property3}) => 
  r.set(property1, { property2, property3 }), new Map())

console.log(Object.fromEntries(result))

使用对象文字作为累加器:

let data = [{ "property1": "x", "property2": "value1", "property3": "value1" }, { "property1": "x", "property2": "value2", "property3": "value2" }, { "property1": "y", "property2": "value3", "property3": "value3" }, { "property1": "y", "property2": "value4", "property3": "value4" } ]

let result = data.reduce((r,{property1, property2, property3}) => { 
  r[property1] = r[property1] || []
  r[property1].push({ property2, property3 })
  return r
}, {})

console.log(result)

答案 4 :(得分:-1)

这是我解决这个问题的方法。我绝不是专家,我相信其他用户可以提供更好的解决方案。但是直到那时您都可以看到是否有帮助。

基本上,我们想使用.filter表达式过滤掉两个集合(x和y)。然后,对于这些集合,我们将删除用于过滤的属性。然后最后创建一个将其余集合组合在一起的新对象。

JSFiddle:https://jsfiddle.net/u9bxg8wv/1/

const dataSource = [
{"property1": "x","property2": "value1","property3": "value1"},
{"property1": "x","property2": "value2","property3": "value2"},
{"property1": "y","property2": "value3","property3": "value3"},
{"property1": "y","property2": "value4","property3": "value4"}
];

let xContainer = dataSource.filter(x => x.property1 === "x");
let yContainer = dataSource.filter(y => y.property1 === "y");

xContainer.forEach((e) => {
  delete e.property1;
});

yContainer.forEach((e) => {
  delete e.property1;
});

let mappedDataSource = {
    "x": xContainer,
    "y": yContainer
};

console.log(mappedDataSource);