使用ES6将对象数组提取到一个数组中

时间:2018-12-04 16:31:25

标签: javascript arrays reactjs ecmascript-6

我正在研究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"
    }
  }
]

我想将源属性中的所有对象提取到具有重复数据删除数据的一个数组中。因此,对于上述JSON数据,基本上我想要一个这样的数组:

[
  {
    "sourceName": "test_demographics",
    "table": "test_demographics_summary"
  },
  {
    "sourceName": "something_demographics",
    "table": "something_demographics_summary"
  }
]

赞赏任何建议。

3 个答案:

答案 0 :(得分:2)

由于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))

答案 1 :(得分:1)

如果您认为自己将拥有各种数据类型,并且sources中缠绕的对象的道具顺序没有不同,则可以将SetArray.reduceJSON.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 sources合并所有spread,然后使用Set通过检查sources的字符串表示形式是否存在来减少它们在集合中。我们只添加那些**不**退出的对象。

请注意,每次处理JSON.stringify和对象比较时,您都受所比较对象中属性顺序的左右,因此,如果对象A为{a: 1, b: 2}而对象B为{b: 2, a: 1}由于字符串表示形式根本不匹配,因此将它们视为不同。因此,只要这不是您的情况,您就应该对此感到满意。

如果您的sources对象中的值仅是字符串,您还可以考虑 使用Array.reduce并按值分组,然后选择第一个数组元素,因为您知道其他元素都是配音:

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))

答案 2 :(得分:0)

我最终做了以下事情:

    // 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));
    })