[英]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);
}
})
偽代碼基本上如下:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.