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

发布于 2025-01-10 06:05:10 字数 1471 浏览 0 评论 0原文

首先是一些经典的免责声明(还有一个大家好,因为我不知道为什么如果我把这两个词放在开头,它会不断地删掉它们!):

  • 这里是超级新手,10天前开始学习Javascript;
  • 我搜索了很多解决方案来解决我的问题,但是经过两天多的尝试解决方案后,我打开了这篇文章,有点痛苦 投降。

我的问题:基本上,从包含大量格式为 {“date”:“MM-DD-YYYY”,“温度”:整数} 的 Json 中,我正在尝试构建一种交互式脚本,该脚本将采取所有该 json 中的不同月份,并会自动给出该月的平均温度。因此,如果您更改数组并添加 1 个月的记录,我会立即获得新月份的新平均值。

因此,从 Json 开始,我的步骤是创建一个数组,其中包含文件中包含的所有月份(并非包含每个月)以及地图和新日期...然后我将转换“javascript 月份”(从从 0...但在 Json 中一月不是 0 而是 1)以“字符串形式”包含月份数组,其中 Jan =“01”,Feb =“02”等。

之后我迷失了:我尝试了很多循环、嵌套循环、forEach的组合,但我无法找到一种方法来对Javascript说:“对于这个数组中的每个项目,获取所有相关记录来自 Json,并给我一个平均温度!”

基本上我想要实现的目标很简单:从给定的该格式的 Json 中,我检索月份数组,最终结果 = 平均温度数组,每个月 1 个平均温度。

我将尝试发布我到目前为止所做的事情(仅功能部分)!

先感谢您!

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]) 



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;
  • 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.

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. So if you change the array and add 1 month of records, immediately I get also the new average for the new month.

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.

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!"

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.

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]) 



如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

幽梦紫曦~ 2025-01-17 06:05:10

对您的代码的一些评论:

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

效率相当低。数据已经是一个数组,不需要通过map创建一个新数组,将其转换为一个集合,然后再转换回另一个数组。另外,不需要创建一个日期来获取月份,更不用说当可以在上面的行中完成时(如果需要)通过另一个地图执行 +1 的效率低下。

ECMAScript 不支持 dd-mm-yyyy 格式,因此解析取决于实现。 Safari 至少将其视为无效日期,请参阅为什么 Date.解析结果不正确?

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

如果需要 +1,最好在第一个地图中执行此操作,即使需要执行此操作,为什么还要创建另一个数组呢?只需使用 forEach 并修改现有数组即可。

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

结果没有在任何地方声明或初始化,所以它不会去任何地方。

您可以使用减少 在数据数组上对特定月份的温度进行求和并生成平均值。将 sum 和 count 的值保留在传递到每个后续循环的累加器中很方便。然后,您可以每次生成一个新的平均值或在最后执行。如果数据文件很大,每次计算平均值会更简单,但效率可能会较低。但对于小文件来说,差异可以忽略不计。

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

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. 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).

The format dd-mm-yyyy is not supported by ECMAScript so parsing is implementation dependent. Safari at least treats it as an invalid date, see 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? Just use forEach and modify the existing array.

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.

You can use reduce on the data array to sum the temperatures for a particular month and generate an average. It's convenient to keep the values for sum and count for a month in the accumulator that is passed to each subsequent loop. 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
));

2025-01-17 06:05:10

我不知道这是否是您想要的,但在这里我创建了一些片段,其中有四个月的时间并平均每个月的温度:

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

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文