#javascript #json #reactjs
#javascript #json #reactjs
Вопрос:
Я получаю файл JSON, который содержит данные о погоде в ряде городов. Вот пример данных.
const weatherArray = [{
"Date": '5-1-19',
"Location": 'New York',
"Rainfall": 4},
{
"Date": '5-1-19',
"Location": 'Miami',
"Rainfall": 8},
{
"Date": '5-1-20',
"Location": 'New York',
"Rainfall": 9},
{
"Date": '5-1-20',
"Location": 'Miami',
"Rainfall": 2},
{
"Date": '5-1-21',
"Location": 'New York',
"Rainfall": 10},
{
"Date": '5-1-21',
"Location": 'Chicago',
"Rainfall": 9},
]
Что мне нужно сделать, это отфильтровать эти данные и сохранить максимальное количество осадков для каждого города в массиве. Я полагаю, что моя функция завершена, но filterData возвращает массив из 6 неизвестных объектов.
filterData = (inputArray) => {
let rain = inputArray.map(obj => rain.find(o => o.Location === obj.Location amp;amp; obj.Rainfall > o.Rainfall) || rain.find(o => o.Location !== obj.Location));
return rain;
}
Я хотел бы, чтобы выходной массив содержал весь объект, связанный с максимальным количеством осадков для каждого города в файле JSON.
rain = [{
"Date": '5-1-19',
"Location": 'Miami',
"Rainfall": 8},
{
"Date": '5-1-21',
"Location": 'New York',
"Rainfall": 10},
{
"Date": '5-1-21',
"Location": 'Chicago',
"Rainfall": 9},
]
Комментарии:
1. пожалуйста, добавьте желаемый результат.
2. у вас разные даты?
Ответ №1:
Вы могли бы взять карту, собрать максимальное количество осадков в местоположении и получить новый массив объектов с результатом.
const
weatherArray = [{ Date: "5-1-19", Location: "New York", Rainfall: 4 }, { Date: "5-1-19", Location: "Miami", Rainfall: 8 }, { Date: "5-1-20", Location: "New York", Rainfall: 9 }, { Date: "5-1-20", Location: "Miami", Rainfall: 2 }, { Date: "5-1-21", Location: "New York", Rainfall: 10 }, { Date: "5-1-21", Location: "Chicago", Rainfall: 9 }],
filterData = (inputArray) => {
return Array.from(
inputArray.reduce((m, { Location, Rainfall }) =>
m.set(Location, Math.max(m.get(Location) || 0, Rainfall)), new Map),
([Location, Rainfall]) => ({ Location, Rainfall })
);
};
console.log(filterData(weatherArray));
.as-console-wrapper { max-height: 100% !important; top: 0; }
С датой.
const
weatherArray = [{ Date: "5-1-19", Location: "New York", Rainfall: 4 }, { Date: "5-1-19", Location: "Miami", Rainfall: 8 }, { Date: "5-1-20", Location: "New York", Rainfall: 9 }, { Date: "5-1-20", Location: "Miami", Rainfall: 2 }, { Date: "5-1-21", Location: "New York", Rainfall: 10 }, { Date: "5-1-21", Location: "Chicago", Rainfall: 9 }],
filterData = (inputArray) => {
return Array.from(inputArray
.reduce((m, o) => {
var temp = m.get(o.Location)
return temp amp;amp; temp.Rainfall > o.Rainfall
? m
: m.set(o.Location, o);
}, new Map)
.values()
);
};
console.log(filterData(weatherArray));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Комментарии:
1. приятно, но это решение не сохраняет дату последнего выпавшего дождя
2. @jsdeveloper, это требуется?
3. может быть, и нет, но это было в желаемом результате, опубликованном выше
Ответ №2:
Ваша функция далека от того, чтобы ее можно было использовать 🙂 Попробуйте вместо этого простое сокращение:
weatherArray.reduce((accumulator, current) => {
// check if given city is already in reducing array result
let cityExists = accumulator.findIndex(k => k.Location === current.Location)
if(cityExists > -1) {
// there is a city in resulting array, check values and perhaps update
if(accumulator[cityExists].Rainfall < current.Rainfall) {
accumulator[cityExists].Rainfall = current.Rainfall
accumulator[cityExists].Date = current.Date
}
} else {
// no such city, just add it
accumulator.push(current)
}
return accumulator
}, []) // start with an empty array
Ответ №3:
Лично я бы разбил задачу на несколько подзадач (вместо того, чтобы пытаться выполнить все это в одной строке), вот так:
задача 1: получить все уникальные местоположения
задача 2: для определенного местоположения найдите максимальное количество осадков
задача 3: объединить уникальные местоположения с соответствующим максимальным количеством осадков
Если вы напишете функцию для каждого из них, я полагаю, вы сможете решить это самостоятельно.
Ответ №4:
Просто используйте reduce
:
const weatherArray = [{
"Date": '5-1-19',
"Location": 'New York',
"Rainfall": 4
},
{
"Date": '5-1-19',
"Location": 'Miami',
"Rainfall": 8
},
{
"Date": '5-1-20',
"Location": 'New York',
"Rainfall": 9
},
{
"Date": '5-1-20',
"Location": 'Miami',
"Rainfall": 2
},
{
"Date": '5-1-21',
"Location": 'New York',
"Rainfall": 10
},
{
"Date": '5-1-21',
"Location": 'Chicago',
"Rainfall": 9
}
];
const rain = weatherArray.reduce((acc, { Date, Location, Rainfall }) => {
if (acc.some(e => e.Location == Location)) {
if (acc.find(e => e.Location == Location).Rainfall > Rainfall) {
return acc;
}
acc.push({ Date, Location, Rainfall});
acc.splice(acc.findIndex(e => e.Location == Location), 1);
return acc;
}
acc.push({ Date, Location, Rainfall });
return acc;
}, []);
console.log(rain);
.as-console-wrapper { max-height: 100% !important; top: auto; }
Ответ №5:
Что я бы вам посоветовал, так это начать разбивать ваше функциональное программирование на более понятные функции (для вас), прежде чем пытаться создавать однострочники.
Существует множество алгоритмов, которые вы можете использовать для своего решения:
- Вы могли бы получить массив результатов для каждого города, отсортировать его и получить самый большой (вероятно, это можно сделать чище с помощью Array.reduce). Очень близко к решению @Maciej Kwas.
- Вы могли бы создать объект для использования в качестве словаря, где при первом поиске города вы сохраняете его название и значение количества осадков, и для каждого элемента в итерации проверяете, есть ли город уже в вашем объекте, и обновляете значение количества осадков, если оно больше.
- Вы можете использовать рекурсию, чтобы сгруппировать ваши значения по городам, а затем выполнить итерацию по ним.
На мой взгляд, я считаю, что вам следует сначала написать читаемый код, а затем беспокоиться о производительности, если только ваши требования к программному обеспечению не требуют, чтобы производительность была превыше всего.
Поэтому моим рекомендуемым решением был бы вариант 2, и это мог бы быть код:
const rain = {};
weatherArray.forEach(weather => {
const currentCity = weather.Location;
if (rain.hasOwnProperty(currentCity) amp;amp; rain[currentCity].Rainfall < weather.Rainfall) {
rain[currentCity] = {Rainfall: weather.Rainfall, Date: weather.Date };
} else {
rain[currentCity] = weather;
};)
rain
будет объектом значений:
{
'Miami': {"Date": '5-1-19',
"Rainfall": 8},
'New York': {
"Date": '5-1-21',
"Rainfall": 10},
'Chicago': {
"Date": '5-1-21',
"Rainfall": 9},
}
Может быть легко преобразован в массив, если это ваш конечный результат.
Если доступен ES2016, вы также можете использовать новые итерации карты.