Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
427 views
in Technique[技术] by (71.8m points)

javascript - 如何通过groupBy on键过滤对象数组?(How to filter an array of objects by groupBy on key?)

I have below algorithmic base problem and I'm trying to solve it with ES6, but I'm getting confused with groupBy ,(我遇到了以下基于算法的基本问题,并且尝试使用ES6进行解决,但是我对groupBy感到困惑,)

let data = [ {id: "2", time: "3/11/2016 02:02:58", value: 7.0}, {id: "1", time: "3/11/2016 02:12:32", value: 6.5}, {id: "1", time: "3/11/2016 02:13:11", value: 7.25}, {id: "4", time: "3/11/2016 02:13:54", value: 8.75}, {id: "2", time: "3/11/2016 05:02:45", value: 11.0}, {id: "4", time: "3/11/2016 06:32:42", value: 5.0}, {id: "2", time: "3/11/2016 06:35:12", value: 2.0}, {id: "1", time: "3/11/2016 06:45:01", value: 12.0}, {id: "1", time: "3/11/2016 06:59:59", value: 11.75}, {id: "2", time: "3/11/2016 07:01:53", value: 1.0}, {id: "1", time: "3/11/2016 07:02:54", value: 4.5}, {id: "3", time: "3/11/2016 07:02:54", value: 15.75}, {id: "6", time: "3/11/2016 07:02:54", value: 14.25}, {id: "2", time: "3/11/2016 07:03:15", value: 12.0}, {id: "2", time: "3/11/2016 08:02:22", value: 3.0}, {id: "2", time: "3/11/2016 09:41:50", value: 4.0}, {id: "2", time: "3/11/2016 10:02:54", value: 5.0}, {id: "2", time: "3/11/2016 11:05:35", value: 10.0}, {id: "2", time: "3/11/2016 13:02:21", value: 6.0}, {id: "5", time: "3/11/2016 13:02:40", value: 8.0}, {id: "4", time: "3/11/2016 13:02:55", value: 8.0}, {id: "5", time: "3/11/2016 13:33:34", value: 8.0}, {id: "5", time: "3/11/2016 13:42:24", value: 8.0}, {id: "5", time: "3/11/2016 13:47:44", value: 6.25}, {id: "5", time: "3/11/2016 14:02:54", value: 4.25}, {id: "5", time: "3/11/2016 14:03:04", value: 5.25}, {id: "5", time: "3/11/2016 15:12:55", value: 6.25}, {id: "2", time: "3/11/2016 16:02:36", value: 8.0}, {id: "5", time: "3/11/2016 16:22:11", value: 8.5}, {id: "5", time: "3/11/2016 17:18:19", value: 11.25}, {id: "5", time: "3/11/2016 18:19:20", value: 9.0}, {id: "2", time: "3/11/2016 23:59:59", value: 9.0} ]; Trying to get subset of array with the following condition:(尝试获取具有以下条件的数组子集:) Each id within each one hour period, only the most expensive value should be in result set.(在每个一小时内的每个id ,结果集中应该只包含最昂贵的值。) If more than one object with the same id equals the most expensive value in a one hour period, only place the earliest one.(如果一个以上具有相同id对象等于一小时内最昂贵的值,则仅放置最早的一个。) If there are more than 8 objects for an id in the overall array of objects, remove it.(如果整个对象数组中一个id对象超过8个,则将其删除。) I know how it's easily achievable in SQL with MAX on 'value' and GroupBy on 'time' column, but here I get confused with the JS loop.(我知道如何在SQL中使用“值” MAX和“时间”列上 GroupBy轻松实现,但是在这里,我对JS循环感到困惑。) Please suggest some tricks if possible.(如果可能,请提出一些技巧。) I was trying like below, but seems still long way to go(我在尝试以下方法,但似乎还有很长的路要走) var newArr = []; data.forEach(function (el) { var findIndex = newArr.findIndex(function (item) { return item.time === el.time; }); if (findIndex === -1) { newArr.push(el); } else if (el.value > newArr[findIndex].value) { newArr[findIndex].value = el.value; newArr[findIndex].time = el.time; } else { newArr[findIndex].time = el.time; } }); just for making it more clear output will be like that(只是为了使输出更加清晰) [ { id: "4",time: "3/11/2016 02:13:54",value: 8.75 }, { id: "1", time: "3/11/2016 06:45:01",value: 12.0 }, { id: "3",time: "3/11/2016 07:02:54",value: 15.75 }, { id: "4", time: "3/11/2016 13:02:55", value: 8.0} ] Record of id: "2" and "5" removed because it has more than 8 appearance I found something here but seems ruby(id的记录:“ 2”和“ 5”已删除,因为它的外观超过了8个,我在这里找到了一些东西但看起来是红宝石)   ask by freedom translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to(你需要)


a) create date objects from the data['time'](a)从数据['时间']创建日期对象)
b) sort the array in some way, using an object.(b)使用对象以某种方式对数组进行排序。)
c) filter out excessive data.(c)过滤掉过多的数据。) Hopefully, the code explains itself.(希望代码能自我解释。) I tried to do it in a dynamic way so you can use this will all kinds of years, months, and days, because I supposed it wasn't just the hours you wanted.(我尝试以一种动态的方式进行操作,因此您可以在数年,数月甚至数天的时间内使用它,因为我认为这不仅仅是您想要的时间。) filterOutOldestIds has a quite ugly nested for loop, but I couldn't figure out a better way, if I wanted it to be dynamic but still manageable.(filterOutOldestIds具有一个非常丑陋的嵌套for循环,但是如果我希望它是动态的但仍可管理的,我想不出更好的方法。) let data = [ {id: "2", time: "3/11/2016 02:02:58", value: 7.0}, {id: "1", time: "3/11/2016 02:12:32", value: 6.5}, {id: "1", time: "3/11/2016 02:13:11", value: 7.25}, {id: "4", time: "3/11/2016 02:13:54", value: 8.75}, {id: "2", time: "3/11/2016 05:02:45", value: 11.0}, {id: "4", time: "3/11/2016 06:32:42", value: 5.0}, {id: "2", time: "3/11/2016 06:35:12", value: 2.0}, {id: "1", time: "3/11/2016 06:45:01", value: 12.0}, {id: "1", time: "3/11/2016 06:59:59", value: 11.75}, {id: "2", time: "3/11/2016 07:01:53", value: 1.0}, {id: "1", time: "3/11/2016 07:02:54", value: 4.5}, {id: "3", time: "3/11/2016 07:02:54", value: 15.75}, {id: "6", time: "3/11/2016 07:02:54", value: 14.25}, {id: "2", time: "3/11/2016 07:03:15", value: 12.0}, {id: "2", time: "3/11/2016 08:02:22", value: 3.0}, {id: "2", time: "3/11/2016 09:41:50", value: 4.0}, {id: "2", time: "3/11/2016 10:02:54", value: 5.0}, {id: "2", time: "3/11/2016 11:05:35", value: 10.0}, {id: "2", time: "3/11/2016 13:02:21", value: 6.0}, {id: "5", time: "3/11/2016 13:02:40", value: 8.0}, {id: "4", time: "3/11/2016 13:02:55", value: 8.0}, {id: "5", time: "3/11/2016 13:33:34", value: 8.0}, {id: "5", time: "3/11/2016 13:42:24", value: 8.0}, {id: "5", time: "3/11/2016 13:47:44", value: 6.25}, {id: "5", time: "3/11/2016 14:02:54", value: 4.25}, {id: "5", time: "3/11/2016 14:03:04", value: 5.25}, {id: "5", time: "3/11/2016 15:12:55", value: 6.25}, {id: "2", time: "3/11/2016 16:02:36", value: 8.0}, {id: "5", time: "3/11/2016 16:22:11", value: 8.5}, {id: "5", time: "3/11/2016 17:18:19", value: 11.25}, {id: "5", time: "3/11/2016 18:19:20", value: 9.0}, {id: "2", time: "3/11/2016 23:59:59", value: 9.0} ]; function filterOnMaxValue(arr) { let MAX_OCCURANCES = 8; var controlObj = {}, sortedArr = []; // don't really need this, but using it for added clarity arr.forEach((el) => { controlObj = setHighestValueBasedOnDate(el, controlObj); }); sortedArr = filterOutOldestIds(controlObj, MAX_OCCURANCES); return sortedArr; } function setHighestValueBasedOnDate(el, controlObj) { let date = new Date(el.time), year = date.getFullYear(), month = date.getMonth(), day = date.getDay(), hour = date.getHours(), id = el.id; controlObj = createDefaultStructure(id, year, month, day, hour, controlObj); let previousEl = controlObj[id][year][month][day][hour]; controlObj[id][year][month][day][hour] = (previousEl && previousEl.value > el.value) ? previousEl : el; return controlObj; } function createDefaultStructure(id, year, month, day, hour, controlObj) { controlObj[id] = controlObj[id] || {}; controlObj[id][year] = controlObj[id][year] || {}; controlObj[id][year][month] = controlObj[id][year][month] || {}; controlObj[id][year][month][day] = controlObj[id][year][month][day] || {}; return controlObj; } function filterOutOldestIds(controlObj, maxAllowedOccurances) { var sortedArr = [], idOccurances = {}, idObj, yearObj, monthObj, dayObj, hourObj; for (id in controlObj) { idOccurances[id] = -1; idObj = controlObj[id]; for (year in idObj) { yearObj = idObj[year]; for (month in yearObj) { dayObj = yearObj[month]; for (hour in dayObj) { hourObj = dayObj[hour]; for (el in hourObj) { idOccurances[id]++; // this check should honestly be in every for loop, apart from 'id in controlObj' if (idOccurances[id] < maxAllowedOccurances) { sortedArr.push(hourObj[el]); } else { break; } } } } } } return sortedArr; } let sortedData = filterOnMaxValue(data); console.log(sortedData); <p>Trying to get subset of array with below condition</p> <ul> <li>Each Id within each one hour period, only the most expensive value should be in resultset.</li> <li>If more than one objects from the same Id equal for the most expensive value in a one hour period, only place the earliest one.</li> <li>If there are more than 8 object for an Id in the overall array of objects, remove it.</li> </ul>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...