Как отсортировать объекты Javascript в массиве с помощью регулярных выражений - PullRequest
4 голосов
/ 06 октября 2019

Я звоню в API и получаю массив с большим количеством объектов. В массиве сотни объектов, и его небольшой фрагмент выглядит примерно так:

[
    {
      "name": "total_kills_glock",
      "value": 70
    },
    {
      "name": "total_kills_mac10",
      "value": 39
    },
    {
      "name": "total_kills_ump45",
      "value": 136
    },
    {
      "name": "total_shots_glock",
      "value": 1262
    },
    {
      "name": "total_hits_glock",
      "value": 361
    }
    {
      "name": "total_shots_mac10",
      "value": 862
    },
    {
      "name": "total_hits_mac10",
      "value": 261
    },
    {
      "name": "total_shots_ump45",
      "value": 1610
    },
    {
      "name": "total_hits_ump45",
      "value": 598
    }
]

Есть ли способ отсортировать массив с помощью регулярных выражений, чтобы он выглядел примерно так:

[
  {
    "name": "glock",
    "kills": 70,
    "shots": 1262,
    "hits": 361
  },
  {
    "name": "mac10",
    "kills": 39,
    "shots": 862,
    "hits": 261
  },
  {
    "name": "ump45",
    "kills": 136,
    "shots": 1610,
    "hits": 598
  }
]

Ответы [ 6 ]

4 голосов
/ 06 октября 2019

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

const raw = [{
    "name": "total_kills_glock",
    "value": 70
  },
  {
    "name": "total_kills_mac10",
    "value": 39
  },
  {
    "name": "total_kills_ump45",
    "value": 136
  },
  {
    "name": "total_shots_glock",
    "value": 1262
  },
  {
    "name": "total_hits_glock",
    "value": 361
  },
  {
    "name": "total_shots_mac10",
    "value": 862
  },
  {
    "name": "total_hits_mac10",
    "value": 261
  },
  {
    "name": "total_shots_ump45",
    "value": 1610
  },
  {
    "name": "total_hits_ump45",
    "value": 598
  }
];

var final = [];
var keys = [];
raw.forEach(v => {
  const m = v.name.match(/^total_([^_]+)_(.+)$/);
  const k = keys.indexOf(m[2]);
  if (k == -1) {
    var o = { name: m[2] };
    o[m[1]] = v.value;
    final.push(o);
    keys.push(m[2]);
  } else {
    final[k][m[1]] = v.value;
  }
});
console.log(final);
4 голосов
/ 06 октября 2019

Вы можете использовать метод lower () для группировки элементов массива, метод split () для извлечения имени и действия из строки name.

var data = [{ "name": "total_kills_glock", "value": 70 }, { "name": "total_kills_mac10", "value": 39 }, { "name": "total_kills_ump45", "value": 136 }, { "name": "total_shots_glock", "value": 1262 }, { "name": "total_hits_glock", "value": 361 }, { "name": "total_shots_mac10", "value": 862 }, { "name": "total_hits_mac10", "value": 261 }, { "name": "total_shots_ump45", "value": 1610 }, { "name": "total_hits_ump45", "value": 598 } ];

var result = data.reduce((acc, curr) => {
  let words = curr.name.split('_');
  let name = words[2];
  let action = words[1];

  let item = acc.find(item => item.name === name);

  if (item) {
    item[action] = curr.value;
  } else {
    acc.push({
      "name": name,
      [action]: curr.value
    });
  }

  return acc;
}, []);

console.log(result);
1 голос
/ 06 октября 2019

Вы можете разбить строку и деструктурировать элементы и взять объект в качестве хеш-таблицы для той же группы. В конце возьмите значения из хеш-таблицы.

var data = [{ name: "total_kills_glock", value: 70 }, { name: "total_kills_mac10", value: 39 }, { name: "total_kills_ump45", value: 136 }, { name: "total_shots_glock", value: 1262 }, { name: "total_hits_glock", value: 361 }, { name: "total_shots_mac10", value: 862 }, { name: "total_hits_mac10", value: 261 }, { name: "total_shots_ump45", value: 1610 }, { name: "total_hits_ump45", value: 598 }],
    result = Object.values(data.reduce((r, { name, value }) => {
        var [, type, name] = name.split('_');
        r[name] = r[name] || { name };
        r[name][type] = value;
        return r;
    }, {}));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 06 октября 2019

Пожалуйста, проверьте это.

let arr=[] //your array
let map=new Map();
arr.forEach((obj)=>{
let x=obj.name.split('_');
map.set(x[2],{"name":x[2],...map.get(x[2]),[x[1]]:obj.value})
}
);
console.log([...map.values()]);

Не стесняйтесь использовать мой репл https://repl.it/repls/PoisedEasyZettabyte, если хотите.

0 голосов
/ 06 октября 2019

Ниже приведено чисто функциональное решение, сочетающее в себе пару полезных приемов. Обратите внимание, что вы можете повторно использовать частичные функции где-то еще в коде. Кроме того, таким образом, вычисления могут распараллеливаться и распределяться (хотя JavaScript еще не существует).

 let raw = [
    {"name": "total_kills_glock", "value": 70},
    {"name": "total_kills_mac10", "value": 39},
    {"name": "total_kills_ump45", "value": 136},
    {"name": "total_shots_glock", "value": 1262},
    {"name": "total_hits_glock", "value": 361},
    {"name": "total_shots_mac10", "value": 862},
    {"name": "total_hits_mac10", "value": 261},
    {"name": "total_shots_ump45", "value": 1610},
    {"name": "total_hits_ump45", "value": 598}
];

//you can use any parsing technique here, including regexp
const parse = name => { 
    const a = name.split("_"); 
    return { key: a[2], metric: a[1] }
};

const groupBy = getKey => (rv, x) => {
    (rv[getKey(x)] = rv[getKey(x)] || []).push(x);
    return rv;
};

//converts [{key,metric,value},...] to {name:key, m1:v1, m2:v2,...} 
const recombine = arr => Object.assign({name: arr[0].key},
    ...Array.from(arr, ({key, metric, value}) => ({[metric]: value}) ));

const groupedByKey = raw
            .map( ({name, ...attrs}) => ({...parse(name), ...attrs}))
            .reduce(groupBy(x => x.key),{});

const result = Object.values(groupedByKey).map(recombine);
console.log(result);

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

0 голосов
/ 06 октября 2019

Возможно, цикл помог бы немного больше, чем использование регулярных выражений для создания нового объекта, не уверен, что я когда-либо видел это раньше.

var rawData = [ { "name": "total_kills_glock", "value": 70 }, { "name": "total_kills_mac10", "value": 39 }, { "name": "total_kills_ump45", "value": 136 }, { "name": "total_shots_glock", "value": 1262 }, { "name": "total_hits_glock", "value": 361 }, { "name": "total_shots_mac10", "value": 862 }, { "name": "total_hits_mac10", "value": 261 }, { "name": "total_shots_ump45", "value": 1610 }, { "name": "total_hits_ump45", "value": 598 } ];

var gunStats = [{
    "name": "glock",
    "kills": 0,
    "shots": 0,
    "hits": 0
},
{
    "name": "mac10",
    "kills": 0,
    "shots": 0,
    "hits": 0
  },
  {
    "name": "ump45",
    "kills": 0,
    "shots": 0,
    "hits": 0
  }
];

rawData.forEach((item)  => { 
    if (item.name.includes("glock")) {
        applyStatsToGun(item, "glock");
    }

    if (item.name.includes("mac10")) {
        applyStatsToGun(item, "mac10");
    }

    if (item.name.includes("ump45")) {
        applyStatsToGun(item, "ump45");
    }

});


function applyStatsToGun(item, gunName) {
    if (item.name.includes(gunName)) {

        if (item.name.includes("kills")) {
            var gun = gunStats.find((gun) => gun.name == gunName);
            gun.kills += item.value;
        }

        if (item.name.includes("shots")) {
            var gun = gunStats.find((gun) => gun.name == gunName);
            gun.shots += item.value;
        }

        if (item.name.includes("hits")) {
            var gun = gunStats.find((gun) => gun.name == gunName);
            gun.hits += item.value;
        }
    }
}


console.log(gunStats);

И если вы не знаете, хотите ли вы жестко закодировать строки с именами пистолетов, скажем, есть сотни, прежде чем вы захотите получить список всех уникальных имен, повторяющихся черезперечислить и проанализировать 3-й элемент в name.split("_")[3], затем выполнить итерацию по этому списку и применить значение вместо жесткого кодирования этих значений

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...