簡體   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

遍歷對象的js數組,然后在每個對象內,針對所有其他對象檢查對象中的值是否唯一,然后推入新數組的一種好方法。

我有一個對象數組:

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"
  }
]

我需要檢查每個對象,如果dt_txt(只是日期,而不是時間,例如:2018-05-23、2018-05-21等)是唯一的,則將該對象推入新數組。

下面是我一直在嘗試的內容,我對代碼進行了注釋以顯示我的思路。

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
}

我遇到的問題是,在自己的地圖函數中推入唯一的日期會導致遞歸問題。 我知道必須有一個更好的方法。 任何幫助或指示都將是一個很大的緩解,我已經為此苦苦掙扎了一段時間。

您可以使用.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); 

請注意,尚不清楚您需要解析日期的魯棒性。 在您的示例中,所有日期均為YYYY-MM-DD格式,因此我只使用了比split或正則表達式快的substring

至於為什么代碼不起作用,是因為您要遍歷uniqueDays但還要在循環內推送它。 那是不可以的。

您發布的代碼每次都會解析uniqueDays的日期。 對於大型集合,這將很慢。 上面的解決方案只需要為每個項目解析一次日期,這樣會更快。

您的代碼使用map但是map根據傳遞給map的函數返回的值生成一個新數組。 在您的情況下,它會生成一個[undefined, undefined, undefined]數組,然后將其扔掉。 您可能想使用forEach

我假設您循環播放是因為您需要繼續解析日期。 如果您不解析日期,則可以使用someArray.indexOf來查找數組中是否有條目,如

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

您還可以使用someArray.findIndex函數的someArray.findIndex ,以便可以使用它來解析日期。

但是,最后,遍歷數組的速度很慢,檢查對象中是否存在屬性的速度很快。 由於數組和對象之間的差異,用於查找屬性的算法O(1)哈希圖)為O(1) ,而在未排序的數組中查找值的算法為O(N/2)

讓我補充一點,@ CertainPerformance的解決方案也很優雅。 它的收集中的對象accum ,然后必須遍歷該對象時,它調用以產生陣列Object.values 對於較大的結果數組,理論上比沒有第二個隱藏循環要慢。

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

偽代碼基本上如下:

  • 通過weatherArray循環
  • 對於每個孩子,檢查日期是否存在於新數組中
    • 如果不存在,則將該對象推入新數組
    • 否則什么都不做

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM