Как я могу сопоставить массив объектов с массивом с идентификатором для повторяющихся значений?

Большая часть того, что я пишу, уже была охвачена Pressacco, но это специфично для SpecFlow.

Я получал это сообщение для элемента , поэтому я добавил файл specflow.xsd в решение этого ответа (с некоторыми изменениями, допускающими элемент ).

После этого я (например, Pressacco), щелкнув правой кнопкой мыши в файловом буфере app.config и выбранных свойств, а внутри Schemas я добавил "specflow.xsd" до конца. Теперь все Schemas читают:

"C:\Program Files (x86)\Microsoft Visual Studio 12.0\xml\Schemas\1033\DotNetConfig.xsd" "C:\Program Files (x86)\Microsoft Visual Studio 12.0\xml\Schemas\EntityFrameworkConfig_6_1_0.xsd" "C:\Program Files (x86)\Microsoft Visual Studio 12.0\xml\Schemas\RazorCustomSchema.xsd" "specflow.xsd"

4
задан isherwood 16 January 2019 в 16:57
поделиться

4 ответа

Используя ваш подход, вы можете использовать filter() внутри карты, чтобы проверить, сколько элементов в исходном массиве имеют одинаковое значение текущего анализируемого, используя это условие, вы можете выбрать, что возвращать в качестве нового значения: [ 1113]

const data = [
  {count: 400, value: "Car Wash Drops"},
  {count: 48, value: "Personal/Seeding"},
  {count: 48, value: "Personal/Seeding"},
];

let res = data.map((x, idx) =>
{
    if (data.filter(y => y.value === x.value).length > 1)
        return [`${x.value} (${idx})`, x.count];
    else
        return [`${x.value}`, x.count];
});

console.log(res);

Производительность предыдущего подхода может быть улучшена, если мы используем some() вместо filter(), например так:

const data = [
  {count: 400, value: "Car Wash Drops"},
  {count: 48, value: "Personal/Seeding"},
  {count: 48, value: "Personal/Seeding"},
  {count: 300, value: "Operators/Management"},
  {count: 48, value: "Personal/Seeding"}
];

let res = data.map((x, idx) =>
{
    if (data.some((y, j) => y.value === x.value && idx !== j))
        return [`${x.value} (${idx})`, x.count];
    else
        return [`${x.value}`, x.count];
});

console.log(res);

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

const data = [
  {count: 400, value: "Car Wash Drops"},
  {count: 48, value: "Personal/Seeding"},
  {count: 48, value: "Personal/Seeding"},
  {count: 300, value: "Operators/Management"},
  {count: 48, value: "Personal/Seeding"}
];

let counters = data.reduce((res, {value}) =>
{
    res.set(value, res.has(value) ? res.get(value) + 1 : 1);
    return res;
}, new Map());

let res = data.map((x, idx) =>
{
    return [
        `${x.value}` + (counters.get(x.value) > 1 ? `(${idx})` : ""),
        x.count
    ]; 
});

console.log(res);

0
ответ дан Shidersz 16 January 2019 в 16:57
поделиться

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

const data = [
  {count: 400, value: "Car Wash Drops"},
  {count: 48, value: "Personal/Seeding"},
  {count: 48, value: "Personal/Seeding"},
];

let valueCounts = data.reduce((a, c) => {
  a[c.value] = a[c.value] || {current: 1, total: 0};
  a[c.value].total += 1;
  return a;
}, {});

const expected = data.map(({count, value}) => {
  if (valueCounts[value].total === 1) return [value, count];
  return [`${value} (${valueCounts[value].current++})`, count];
});

console.log(expected);

0
ответ дан slider 16 January 2019 в 16:57
поделиться

Ответ уже был дан, при всем уважении к автору ответа, я утверждаю, что могут быть сделаны некоторые улучшения в ответе, как синтаксически, так и с точки зрения производительности:

  1. [1117 ] reduce следует избегать, если источник очень большой, хотя я всегда предпочитаю reduce, если источник относительно мал (data.length < 1000). Попробуйте использовать POF (обычный старый для :)) , так как это самый быстрый вариант.

  2. Карта ES6 является хорошим помощником, когда мы имеем дело с парами ключ-значение , но я предпочитаю POO (plain old object:) ), если это возможно и это сделает наш код более эстетичным.

Я предоставлю свое решение этой проблемы (в худшем случае он запустит O (n) и использует дополнительное пространство O (n) для пар ключ-значение, он выполнит два прохода на источнике, второй проход необходим, чтобы поставить 1 там, где мы пропустили, когда мы впервые встретились с ним на первом проходе):

let data =  [
  {count: 400, value: "Car Wash Drops"},
  {count: 48, value: "Personal/Seeding"},
  {count: 48, value: "Personal/Seeding"},
  {count: 300, value: "Operators/Management"},
  {count: 48, value: "Personal/Seeding"}
];

const map = {};

for (let i=0;i<data.length;i+=1) {
  map[ data[i].value ] = map[ data[i].value ]+1 || 0;
  data[i].value = map[data[i].value]?data[i].value+` (${map[data[i].value]+1})`:data[i].value; 
}

for (let i=0;i<data.length;i+=1) {
  data[i].value = map[data[i].value]?data[i].value+` (1)`:data[i].value; 
}

console.log(data.map(o=>[o.value,o.count]));

или более краткая версия с использованием оператора ES6 of [ссылка на] :

let data =  [
      {count: 400, value: "Car Wash Drops"},
      {count: 48, value: "Personal/Seeding"},
      {count: 48, value: "Personal/Seeding"},
      {count: 300, value: "Operators/Management"},
      {count: 48, value: "Personal/Seeding"}
    ];

    const map = {};

    for (let d of data) {
      map[d.value] = map[d.value]+1 || 0;
      d.value = map[d.value]?d.value+` (${map[d.value]+1})`:d.value; 
    }

    for (let d of data) {
      d.value = map[d.value]?d.value+` (1)`:d.value; 
    }

    console.log(data.map(o=>[o.value,o.count]));

0
ответ дан Humoyun 16 January 2019 в 16:57
поделиться

Вы можете передать второй аргумент .map() после обратного вызова. Это значение будет использоваться в качестве значения this при вызове обратного вызова. Таким образом, вы можете пройти через объект, который вы можете использовать для накопления количества повторений:

data.map(function(d, i) {
  if (!(d.value in this))
    this[d.value] = 0;
  else
    this[d.value] += 1;

  return [
    d.value + (this[d.value] ? " (" + this[d.value] + ")" : ""),
    d.count
  ];
}, {});

Начиная с пустого объекта, обратный вызов может отслеживать, сколько раз он видел каждую строку d.value , Когда он видит повтор, он может добавить спецификатор к строке.

Так вот, это не совсем соответствует тому, что вы просили, потому что оно рассматривает только одно значение за раз. Таким образом, в первый раз, когда он видит "Personal/Seeding", он не знает, что это дубликат, поэтому он не изменяется с помощью спецификатора. Второй раз через это, конечно.

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

0
ответ дан Pointy 16 January 2019 в 16:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: