简体   繁体   English

遍历对象的js数组,在每个对象内,针对所有其他对象检查对象中的值是否唯一,并推送到新数组

[英]iterate over a js array of objects, within each object, check a value in the object against all others for uniqueness, push to new array

What is a good way to iterate over a js array of objects, and then within each object, check a value in the object against all others for uniqueness, and push to a new array. 遍历对象的js数组,然后在每个对象内,针对所有其他对象检查对象中的值是否唯一,然后推入新数组的一种好方法。

I have an array of objects: 我有一个对象数组:

const weatherArray = [
  {
    dt: 1526871600
    dt_txt: "2018-05-21 03:22:00"
  },
  {
    dt: 1526871600
    dt_txt: "2018-05-22 03:30:00"
  },
  {
    dt: 1526871600
    dt_txt: "2018-05-21 03:50:00"
  },
  {
    dt: 1526871600
    dt_txt: "2018-05-23 03:17:00"
  },
  {
    dt: 1526871600
    dt_txt: "2018-05-23 03:23:00"
  }
]

I need to check each object and if the dt_txt (just date, not time eg: 2018-05-23, 2018-05-21 etc) is unique, push that object into a new array. 我需要检查每个对象,如果dt_txt(只是日期,而不是时间,例如:2018-05-23、2018-05-21等)是唯一的,则将该对象推入新数组。

Below is what I have been trying, I commented to the code to show my train of thought. 下面是我一直在尝试的内容,我对代码进行了注释以显示我的思路。

var uniqueDays = []
function getDays(weatherArray) {
  // push first value to new array to compare against other items
  uniqueDays.push(weatherArray[0])
  // get just the yyyy-mm-dd from txt we're comparing against
  let firstDayString = weatherArray[0].dt_txt.split(" ")[0]

  weatherArray.map((day) => {
    let dayString = day.dt_txt.split(" ")[0]

    uniqueDays.map((uniqueDay, index) => {
      // get just the yyyy-mm-dd for new array items
      let unqiueDayString = uniqueDay.dt_txt.split(" ")[0]

      // if the value exists, do nothing
      if (unqiueDayString == dayString) {
        console.log('duplicate');
      } else {
        // otherwise push to new array (this is the issue)
        uniqueDays.push(day)
      }
    })
  })

  return uniqueDays
}

The issue I am having is that pushing to unique day's within it's own map function is causing a recursion issue. 我遇到的问题是,在自己的地图函数中推入唯一的日期会导致递归问题。 I know there has to be a better way to this. 我知道必须有一个更好的方法。 Any help or direction would be a big relief, I've been struggling with this for some time. 任何帮助或指示都将是一个很大的缓解,我已经为此苦苦挣扎了一段时间。

You can group objects in an array with .reduce , putting each unique date into an object indexed by date and then getting that object's values: 您可以使用.reduce将数组中的对象分组,将每个唯一日期放入按日期索引的对象中,然后获取该对象的值:

 const weatherArray=[{dt:1526871600,dt_txt:"2018-05-21 03:22:00"},{dt:1526871600,dt_txt:"2018-05-22 03:30:00"},{dt:1526871600,dt_txt:"2018-05-21 03:50:00"},{dt:1526871600,dt_txt:"2018-05-23 03:17:00"},{dt:1526871600,dt_txt:"2018-05-23 03:23:00"}]; const output = Object.values( weatherArray.reduce((accum, obj) => { const date = obj.dt_txt.slice(0, 10); if (!accum[date]) accum[date] = obj; return accum; }, {}) ); console.log(output); 

 const weatherArray = [ { dt: 1526871600, dt_txt: "2018-05-21 03:22:00" }, { dt: 1526871600, dt_txt: "2018-05-22 03:30:00" }, { dt: 1526871600, dt_txt: "2018-05-21 03:50:00" }, { dt: 1526871600, dt_txt: "2018-05-23 03:17:00" }, { dt: 1526871600, dt_txt: "2018-05-23 03:23:00" } ] const seen = {}; const res = weatherArray.filter(function(dt){ const date = dt.dt_txt.substring(0, 10); if (!seen[date]) { seen[date] = true; return true; } }); console.log(res); 

note that it's not clear how robust you need to parse your dates. 请注意,尚不清楚您需要解析日期的鲁棒性。 Looking at your example all dates are in the format YYYY-MM-DD so I just used substring which would be faster than split or a regular expression. 在您的示例中,所有日期均为YYYY-MM-DD格式,因此我只使用了比split或正则表达式快的substring

As for why your code doesn't work it's because you're looping over uniqueDays but also pushing to it inside the loop . 至于为什么代码不起作用,是因为您要遍历uniqueDays但还要在循环内推送它。 That's a no-no. 那是不可以的。

The code you posted is parsing the dates in uniqueDays every time. 您发布的代码每次都会解析uniqueDays的日期。 For a large collection that would be slow. 对于大型集合,这将很慢。 The solution above only needs to parse the dates once per item so that would be faster. 上面的解决方案只需要为每个项目解析一次日期,这样会更快。

Your code uses map but map generates a new array from whatever the function passed to map returns. 您的代码使用map但是map根据传递给map的函数返回的值生成一个新数组。 In your case it's generating an array of undefined as in [undefined, undefined, undefined] and then throwing that array away. 在您的情况下,它会生成一个[undefined, undefined, undefined]数组,然后将其扔掉。 You probably wanted to use forEach . 您可能想使用forEach

I'm assuming you looped because you needed to keep parsing the dates. 我假设您循环播放是因为您需要继续解析日期。 If you didn't parse the dates you can use someArray.indexOf to find if there is an entry in an array as in 如果您不解析日期,则可以使用someArray.indexOf来查找数组中是否有条目,如

const isInArray = someArray.indexOf(value) >= 0; 

You can also use someArray.findIndex which takes a function so you could have used that to parse the dates. 您还可以使用someArray.findIndex函数的someArray.findIndex ,以便可以使用它来解析日期。

But, finally, looking through an array is slow, checking if a property exists in an object is fast. 但是,最后,遍历数组的速度很慢,检查对象中是否存在属性的速度很快。 Because of the differences between arrays and objects the algorithm for finding a property, a hashmap, is O(1) where as to find an value in an unsorted array is O(N/2) . 由于数组和对象之间的差异,用于查找属性的算法O(1)哈希图)为O(1) ,而在未排序的数组中查找值的算法为O(N/2)

Let me add that @CertainPerformance's solution is also elegant. 让我补充一点,@ CertainPerformance的解决方案也很优雅。 It's collecting the objects in accum and then has to iterate over that object to generate an array when it calls Object.values . 它的收集中的对象accum ,然后必须遍历该对象时,它调用以产生阵列Object.values For a large result array that would theoretically be slower than not having that second hidden loop. 对于较大的结果数组,理论上比没有第二个隐藏循环要慢。

 const newUniqWeatherArray = [];

weatherArray.forEach(x => {
  const date = x.dt_txt.split(' ')[0];

  if(!newUniqWeatherArray.some((x) => x.dt_txt.split(' ')[0] === date)){
    newUniqWeatherArray.push(x);
  }
})

Basically the pseudocode is as below: 伪代码基本上如下:

  • Loop thru weatherArray 通过weatherArray循环
  • For each of the child, check if the date exist in new array 对于每个孩子,检查日期是否存在于新数组中
    • If not exist, push this object into the new array 如果不存在,则将该对象推入新数组
    • else do nothing 否则什么都不做

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 迭代对象数组并将模板应用于其中的每个对象 - Iterate over an array of objects and apply a template to each object within Javascript:迭代嵌套在 object 中的对象数组作为值 - Javascript: Iterate over an array of objects nested within an object as a value jQuery $.each - 遍历对象数组并为每个对象选择一个字段 - jQuery $.each - Iterate over an array of objects and select a field for each object 迭代对象数组并仅获取特定键以在反应 js 中形成 object 的新数组 - iterate over array of objects and fetch only specific key to form a new array of object in react js 遍历 JS 中的对象数组 - Iterate over an object array in JS 迭代对象数组并更改每个对象中的一个属性 - Iterate over array of objects and change one property in each object 如何将新属性推入对象数组中的每个现有对象? - How to push new property into each existing object within object array? 迭代两个对象数组并创建新的数组对象 - Iterate over two arrays of objects and create new array object 如何遍历对象数组以创建新的 object? - How do you iterate over an array of objects to create a new object? 检查 object 值是否存在于 Javascript 对象数组中,如果不存在,则将新的 object 添加到数组中 - Check if object value exists within a Javascript array of objects and if not add a new object to array
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM