过滤JSON文件并查找值

时间:2019-03-30 22:21:16

标签: 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 && 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},
]

5 个答案:

答案 0 :(得分:3)

您可以拍摄一张地图,收集一个位置的最大降雨量,并使用结果获得一个新的对象阵列。

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 && 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 :(得分:1)

您的功能远远不能使用:) 尝试使用简单的reduce代替:

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

答案 2 :(得分:0)

就个人而言,我会将任务分解为几个子任务(而不是尝试全部都在一行中完成),就像这样:

任务1::获取所有唯一位置

任务2::查找特定位置的最大降雨量

任务3:将唯一的位置与其各自的最大降雨量结合起来

如果您为每个函数编写一个函数,我相信您应该能够自行解决。

答案 3 :(得分:0)

我建议您在尝试创建单行代码之前,先将函数式编程拆分为更易于理解的函数(为您使用)。

您可以将多种算法用于解决方案:

  • 您可以为每个城市获得一组结果,将其排序并得到最大的结果(使用Array.reduce可能更清洁)。非常接近@Maciej Kwas解决方案。
  • 您可以创建一个对象用作字典,在其中,当您首次找到城市时,将其名称和降雨值存储起来,并针对迭代中的每个元素检查该对象中是否已存在该城市并更新更大的降雨值。
  • 您可以使用递归对每个城市的值进行分组,然后遍历它们。

我认为,除非您的软件需求要求性能优先,否则您应该首先编写可读代码,然后再担心性能。

因此,选项2是我推荐的解决方案,它可能是代码:

const rain = {};
weatherArray.forEach(weather => {
    const currentCity = weather.Location;
    if (rain.hasOwnProperty(currentCity) && 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可用,您还可以使用新的Map迭代器。

答案 4 :(得分:0)

只需使用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; }