Как я могу отсортировать ответ Axios?

#javascript #node.js #sorting #data-structures #axios

#javascript #node.js #сортировка #структуры данных #axios

Вопрос:

Я использую Axios для выполнения запроса GET к общедоступному API, мне нужно объединить имена, если они совпадают, и добавить значения, чтобы отображать только верхние 20 (это большой набор данных) на основе от самых высоких до самых низких значений (в порядке возрастания).

Ответ Axios

  [
    {
        name: "foo1",
        value: "8123.30"
    }, 
    
    {
        name: "foo1",
        value: "2852.13"
        
    }, 
    
    {
        name: "foo2",
        value: "5132.23"
    },
   
    {
        name: "foo1",
        value: "1224.20"
       
    }, 

     {
        name: "foo2",
        value: "1285.23"
        
    }
   1200...
];
  

Ожидаемый результат

 [
  {   name: "foo1",
      value: "12199.63" // from all combined "foo1" amounts in the dataset
  },

  {
     name: "foo2",
     value: "6417.46"  // from all combined "foo2" amounts in the dataset
  },
    18..
]
  

Я пытался сделать что-то подобное….

 const fetchData = () => {
    return axios.get(url)
    .then((response) => response.data)
};

function onlyWhatINeed() {
  const newArr = []
  return fetchData().then(data => {
    const sortedData = data.sort((a, b) => parseFloat(a.value) - parseFloat(b.value)); 
    // I need to loop through the dataset and add all the "values" up
   // returning only the top 20 highest values in an array of those objects 
    newArr.push(sortedData)
  })
}
  

Но я не понимаю, как перенести эти данные в новый массив отсортированных данных (20 лучших значений в порядке возрастания) и использовать эти данные в моем веб-приложении. Я немного новичок в создании REST API, поэтому, если бы вы могли предоставить статьи и / или ресурсы, чтобы я мог понять немного больше, это было бы потрясающим бонусом!

Комментарии:

1. Насколько велик этот набор данных (сколько записей)?

2. Axios возвращает 1220 объектов

Ответ №1:

Вы можете объединить записи с одинаковыми именами, используя карту, затем отсортировать карту и сохранить первые двадцать элементов :

 function onlyWhatINeed() {
  const newArr = []
  return fetchData().then(data => {
    let map = new Map();
    data.forEach(d => {
      if(!map.has(d.name)) {
        map.set(d.name, parseFloat(d.value));
      } else {
        map.set(d.name, map.get(d.name)   parseFloat(d.value));
      }
    })
  
    return Array.from(map.entries()).sort((a, b) => a.value - b.value).slice(0, 20);

  })
}
  

Поскольку вы имеете дело с большим набором данных, я рекомендую вам обрабатывать эту серверную часть вместо того, чтобы перегружать сортировку своим клиентам.

Ответ №2:

 async function fetchData(){
    const { data } = await axios.get(url);
    let newArr = []
    data.forEach((e,i) => {
        let index = newArr.findIndex(el => el.name === e.name);
        if(index !== -1 ) newArr[index].value  = parseFloat(e.value); //add to the value if an element is not unique
        if(index === -1 ) newArr.push({...e, value: parseFloat(e.value)}); //push to the array if the element is unique and convert value to float
    });
    return newArr.sort((a,b) => a.value - b.value).slice(0,20);//returns an array of 20 elements after sorting
}
  

Пожалуйста, проведите дополнительные исследования о том, как работать с массивами и объектами в целом.

Ответ №3:

Если вы уже используете Lodash, то вот решение в функциональном стиле, использующее цепочку lodash. Вероятно, не оптимальная производительность, но может быть полезно для относительно небольших наборов данных.

 const _ = require('lodash');

const data =  [
  {
    name: "foo1",
    value: "8123.30"
  },
  {
    name: "foo1",
    value: "2852.13"
  },
  {
    name: "foo2",
    value: "5132.23"
  },
  {
    name: "foo1",
    value: "1224.20"
  },
  {
    name: "foo2",
    value: "1285.23"
  },
  {
    name: "foo3",
    value: "1000.00"
  },
  {
    name: "foo3",
    value: "2000.00"
  }
];
 
// 1. convert string values to floats
// 2. group by name
// 3. sum values by name
// 4. sort by descending value
// 5. take top 20
const output =
  _(data)
    .map(obj => ({
      name: obj.name,
      value: parseFloat(obj.value)
    }))
    .groupBy('name')
    .map((objs, key) => ({
      name: key,
      value: _.sumBy(objs, 'value')
    }))
    .orderBy(['value'], 'desc')
    .slice(0, 20)
    .value();

console.log('output:', output);