我正在从事ReactJS项目,并拥有以下JSON数据:
[
{
"sources": [
{
"sourceName": "test_demographics",
"table": "test_demographics_summary"
}
],
"userId": "test",
"queryType": {
"mixedQuery": false,
"queryTable": "test_a_query"
}
},
{
"sources": [
{
"sourceName": "something_demographics",
"table": "something_demographics_summary"
},
{
"sourceName": "something_demographics",
"table": "something_demographics_summary"
}
],
"userId": "test",
"queryType": {
"mixedQuery": false,
"queryTable": "test_bquery"
}
}
]我想要将sources属性中的所有对象提取到一个带有deduped数据的数组中。因此,基本上对于上面的JSON数据,我想要一个如下所示的数组:
[
{
"sourceName": "test_demographics",
"table": "test_demographics_summary"
},
{
"sourceName": "something_demographics",
"table": "something_demographics_summary"
}
]谢谢你的建议。
发布于 2018-12-07 09:34:01
最后我做了以下几件事:
// extract sources arrays
let sources = queryObjects.map(function (queryObject) {
return queryObject.sources;
})
// add sources objects into one array and remove duplicates
let sourcesArray = sources.reduce((acc, currValue) => {
return _.uniq(acc.concat(currValue));
})发布于 2018-12-04 16:53:18
由于javascript通过引用来比较对象,所以您需要发明一种按值进行比较的方法。一种方法是序列化对象并将序列化版本存储在一个集合中。在这里,您可以通过获取Object.entries()、对键进行排序并对它们进行JSON.stringify来序列化。一旦您这样做了,这只是一个循环的问题,并添加您没有看到的集和输出。类似于:
let arr = [{"sources": [{"sourceName": "test_demographics","table": "test_demographics_summary"}],"userId": "test","queryType": {"mixedQuery": false,"queryTable": "test_a_query"}},{"sources": [{"sourceName": "something_demographics","table": "something_demographics_summary"},{"sourceName": "something_demographics","table": "something_demographics_summary"}],"userId": "test","queryType": {"mixedQuery": false,"queryTable": "test_bquery"}}]
function getUniqueSources(arr){
let seen = new Set // holds serialized object
return arr.reduce((arr, item) => {
item.sources.forEach(source =>{
// need to sort so key order doesn't matter for equality
let serial = JSON.stringify(Object.entries(source).sort((a, b) => a[0].localeCompare(b[0])))
if (!seen.has(serial)) {
seen.add(serial)
arr.push(source)
}
})
return arr
},[])
}
console.log(getUniqueSources(arr))
发布于 2018-12-04 17:50:55
如果您认为您有不同的数据类型,并且sources缠绕中的对象没有不同的支持顺序,那么您可以使用Set与Array.reduce和JSON.stringify将它们转换为字符串进行比较:
const data = [ { "sources": [ { "sourceName": "test_demographics", "table": "test_demographics_summary" } ], "userId": "test", "queryType": { "mixedQuery": false, "queryTable": "test_a_query" } }, { "sources": [ { "sourceName": "something_demographics", "table": "something_demographics_summary" }, { "sourceName": "something_demographics", "table": "something_demographics_summary" } ], "userId": "test", "queryType": { "mixedQuery": false, "queryTable": "test_bquery" } } ]
const exists = (s, v) => {
const json = JSON.stringify(Object.entries(v))
return s.has(json) ? true : (s.add(json), false)
}
const getUniques = arr => {
let merged = data.reduce((r,c) => [...r.sources, ...c.sources]), s = new Set()
return merged.reduce((r,c) => !exists(s, c) ? (r.push(c), r) : r, [])
}
console.log(getUniques(data))
这样做的想法是首先通过ES6 spread合并所有的sources,然后通过检查sources的字符串表示形式是否已经存在于集合中来使用Set来减少它们。我们只添加**不存在于集合中的那些。
请注意,每次处理JSON.stringify和对象比较时,您都要根据所比较对象中属性的顺序来处理,因此如果对象A是{a: 1, b: 2},对象B是{b: 2, a: 1},则它们将被视为不同,因为它们的字符串表示形式根本不匹配。因此,只要这不是您的场景,您就应该对此很在行。
但是,如果您的sources对象中的值将仅为字符串,则还可以考虑使用Array.reduce并按值分组,只需选择第一个数组元素,因为您知道其他数组元素是dub:
const data = [ { "sources": [ { "sourceName": "test_demographics", "table": "test_demographics_summary" } ], "userId": "test", "queryType": { "mixedQuery": false, "queryTable": "test_a_query" } }, { "sources": [ { "sourceName": "something_demographics", "table": "something_demographics_summary" }, { "sourceName": "something_demographics", "table": "something_demographics_summary" } ], "userId": "test", "queryType": { "mixedQuery": false, "queryTable": "test_bquery" } } ]
const getUniques = arr => {
const merged = data.reduce((r,c) => [...r.sources, ...c.sources])
return Object.values(merged.reduce((r,c) => {
r[Object.values(c).join()] = c
return r
}, {}))
}
console.log(getUniques(data))
https://stackoverflow.com/questions/53617510
复制相似问题