简体   繁体   English

Javascript:用一个数组的元素过滤 Json object 中的一个键?

[英]Javascript: Filtering a key in Json object with the elements of one array?

a couple of classic disclaimers first (and a Hello everyone, because I don't know why it keeps cutting these 2 words if I put them at the beginning:):首先是几个经典的免责声明(还有大家好,因为我不知道为什么如果我把它们放在开头,它会一直删掉这两个词:):

  • Super newbie here, started learning Javascript 10 days ago;超级菜鸟,10天前开始学习Javascript;
  • I searched a lot for a solution to my problem, but after more than 2 days trying solutions, I open this post, a sort of painful surrender.我搜索了很多问题的解决方案,但在尝试了 2 天多的解决方案后,我打开了这篇文章,这是一种痛苦的投降。

My problem: basically, from a Json which contains a lot of records in the format {"date": "MM-DD-YYYY", "temperature": integer} I am trying to build a sort of interactive script that will take all the different months in that json, and will automatically give me the average temperature for that month.我的问题:基本上,从 Json 中包含大量格式为 {"date": "MM-DD-YYYY", "temperature": integer} 的记录json 中的不同月份,并会自动给我该月的平均温度。 So if you change the array and add 1 month of records, immediately I get also the new average for the new month.因此,如果您更改数组并添加 1 个月的记录,我会立即得到新月份的新平均值。

So, starting from the Json, my steps are to make an array with all the months included in the file (not every month is included) with a map and new date... then I will transform the "javascript months" (which starts from 0... but in the Json january is not 0 but 1) to make an array of months included in "string form" where Jan = "01", Feb = "02" and so on.因此,从 Json 开始,我的步骤是创建一个数组,其中包含文件中包含的所有月份(不是每个月都包含在内)以及 map 和新日期......然后我将转换“javascript 月份”(开始从 0... 但在 Json 中,一月不是 0,而是 1) 以制作包含在“字符串形式”中的月份数组,其中 Jan =“01”,Feb =“02”等。

After that I am lost: I have tried a lot of combination with loops, nested loops, forEach, but I can't figure out a way to say to Javascript: "for every item in this array of months, take all the relative records from the Json, and give me an Avg Temperature!"在那之后我迷路了:我尝试了很多与循环、嵌套循环、forEach 的组合,但我想不出一种方法来对 Javascript 说:“对于这个月份数组中的每个项目,获取所有相关记录从 Json 给我一个平均温度!”

Basically what I would like to achieve is simple: from a given Json in that format, I retrieve an array of the months, and the end results = an array of average temperatures, 1 avg temp for every month.基本上我想要实现的目标很简单:从给定的 Json 格式中,我检索月份数组,最终结果 = 平均温度数组,每个月 1 个平均温度。

I'll try to post what I did until now (only the functioning parts)!我将尝试发布我到目前为止所做的(仅功能部分)!

Thank you in advance!先感谢您!

const dates =   [
{"date": "01-24-2020", "temps": 1},
{"date": "01-31-2020", "temps": -1},
{"date": "02-01-2020", "temps": 6},
{"date": "02-02-2020", "temps": 2},
{"date": "03-03-2020", "temps": 1},
{"date": "03-04-2020", "temps": 1},
{"date": "04-06-2020", "temps": -2},
{"date": "04-08-2020", "temps": -4}]

const singleMonths = Array.from(new Set(dates.map(elem => new Date(elem.date).getMonth())))

const singleMonthString = singleMonths.map(m => `${"0"+(m+1)}`)

//after this I tried A LOT of different solutions, but I can only filter manually for a singular item in my Array, and not how I would like to, automatically for all my items in my array!

const damnFilter = dates.filter(m => m.dates.substring(0,2)==result[0]) 



I don't know if it is that you want, but here I created some of the snippet, where it gets four months and averages each month temperature:我不知道它是否是你想要的,但在这里我创建了一些片段,它有四个月的时间和每个月的平均温度:

let newDates = [];
for(let i = 1; i <= 12; i++){
    newDates = dates.filter(date => new Date(date.date).getMonth() + 1 == i)
    if(newDates.length > 0){
    let accumulator = 0;
    newDates.map(day => accumulator += day.temps);
    console.log("Average: ", accumulator / newDates.length);
    }
}

Some comments on your code:对您的代码的一些评论:

 const singleMonths = Array.from(new Set(dates.map(elem => new Date(elem.date).getMonth())))

is quite inefficient.效率很低。 The data is already an array, there's no need to create a new array through map , convert it to a set, then back to another array.数据已经是一个数组,不需要通过map创建一个新数组,将其转换为一个集合,然后再返回另一个数组。 Also, there's no need to create a Date to get the month, not to mention the inefficiency of doing the +1 via another map when it could be done in the above line (if it was needed).此外,无需创建 Date 来获取月份,更不用说通过另一个 map 执行 +1 的低效率了,而它可以在上面的行中完成(如果需要的话)。

The format dd-mm-yyyy is not supported by ECMAScript so parsing is implementation dependent. ECMAScript 不支持 dd-mm-yyyy 格式,因此解析依赖于实现。 Safari at least treats it as an invalid date, see Why does Date.parse give incorrect results? Safari 至少将其视为无效日期,请参阅Why does Date.parse give incorrect results?

 const singleMonthString = singleMonths.map(m => `${"0"+(m+1)}`)

If the +1 was needed, better to do it in the first map, and even if you need to do it, why create another array?如果需要 +1,最好在第一个 map 中完成,即使需要,为什么还要创建另一个数组? Just use forEach and modify the existing array.只需使用forEach并修改现有数组。

 const damnFilter = dates.filter(m => m.dates.substring(0,2)==result[0])

result isn't declared or initialised anywhere so that's not going anywhere. result没有在任何地方声明或初始化,所以它不会去任何地方。

You can use reduce on the data array to sum the temperatures for a particular month and generate an average.您可以对数据数组使用reduce来对特定月份的温度求和并生成平均值。 It's convenient to keep the values for sum and count for a month in the accumulator that is passed to each subsequent loop.在传递给每个后续循环的累加器中将 sum 和 count 的值保留一个月很方便。 You can then generate a new average each time or do it at the end.然后您可以每次生成一个新的平均值或在最后生成一个平均值。 Calculating the average each time is simpler but possibly less efficient if the data file is large.如果数据文件很大,每次计算平均值会更简单,但效率可能会降低。 But for a small file the difference will be negligible.但是对于小文件来说,差异可以忽略不计。

 let data = [ {"date": "01-24-2020", "temps": 1}, {"date": "01-31-2020", "temps": -1}, {"date": "02-01-2020", "temps": 6}, {"date": "02-02-2020", "temps": 2}, {"date": "03-03-2020", "temps": 1}, {"date": "03-04-2020", "temps": 1}, {"date": "04-06-2020", "temps": -2}, {"date": "04-08-2020", "temps": -4} ]; let averageData = data.reduce((acc, obj) => { // Get month number let month = obj.date.slice(0,2); // If accumulator doesn't have a summary object for // that month, add it with initial values if (:acc[month]) { acc[month] = {sum,0: count,0: year. obj.date;slice(-4)}. } // Update summary values for the month acc[month].sum += obj;temps. acc[month];count += 1. acc[month].average = acc[month].sum / acc[month];count; // Return the accumulator return acc, // Use a completely emtpy object for the accumulator }. Object;create(null)). // Show averageData object console;log(averageData): // Show data as month. average Object.keys(averageData).forEach(key => console.log( new Date(averageData[key],year. key-1),toLocaleString('en':{month,'short': year:'numeric'}) + '. ' + averageData[key];average ));

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM