Javascript: удаление дубликатов в массиве объектов с использованием одного свойства - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть такой объект, где 'id' уникален. Мне нужно удалить дубликаты из массива объектов в javascript в любой версии, меньшей, чем ES5. Мне нужно сравнить на основе поля id и удалить его дубликаты.

Пример:

Object = [
{id: id_one, value: value_one, label: ABC},
{id: id_one, value: value_one, label: ABC},
{id: id_three, value: value_three, label: ABX},
{id: id_two, value: value_two, label: ABY},
{id: id_four, value: value_four, label: ABD}
];

Вывод:

result = [
{id: id_one, value: value_one, label: ABC},
{id: id_three, value: value_three, label: ABX},
{id: id_two, value: value_two, label: ABY},
{id: id_four, value: value_four, label: ABD}
];

Я попробовал logi c, как это ,

function getDistValues(object) {
  var distObject = [];
  var tempIndex = [];
  var length = object.length;

  for (var i = 0; i < length; i++) {
    tempIndex.push(object[i].id);

    if (tempIndex.indexOf(object[i].id) === -1 || i === 0) {
      distObject.push(object[i]);
    }
  }

  return distObject;
}

Дает только первый объект. Я пытался сопоставить идентификаторы и сравнить их, но не сработало.

Любая помощь будет полезна для меня.

Ответы [ 6 ]

1 голос
/ 03 апреля 2020

Вы можете взять свойство Set для id и отфильтровать, если id отсутствует в наборе.

var array = [{ id: 'id_one', value: 'value_one', label: 'ABC' }, { id: 'id_one', value: 'value_one', label: 'ABC' }, { id: 'id_three', value: 'value_three', label: 'ABX' }, { id: 'id_two', value: 'value_two', label: 'ABY' }, { id: 'id_four', value: 'value_four', label: 'ABD' }],
    unique = array.filter((ids => ({ id }) => !ids.has(id) && ids.add(id))(new Set));

console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Подход для более старых JS версий

var array = [{ id: 'id_one', value: 'value_one', label: 'ABC' }, { id: 'id_one', value: 'value_one', label: 'ABC' }, { id: 'id_three', value: 'value_three', label: 'ABX' }, { id: 'id_two', value: 'value_two', label: 'ABY' }, { id: 'id_four', value: 'value_four', label: 'ABD' }],
    ids = {},
    unique = [],
    i;

for (i = 0; i < array.length; i++) {
    if (ids[array[i].id]) continue;
    unique.push(array[i]);
    ids[array[i].id] = true;
}

console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 03 апреля 2020

Это потому, что вы всегда добавляете идентификатор в массив tempIndex, поэтому он всегда думает, что текущий является дубликатом. Попробуйте:

function getDistValues(object) {
  var distObject = [];
  var tempIndex = [];
  var length = object.length;

  for (var i = 0; i < length; i++) {    
    if (tempIndex.indexOf(object[i].id) === -1 || i === 0) {
      tempIndex.push(object[i].id);
      distObject.push(object[i]);
    }
  }

  return distObject;
}
0 голосов
/ 03 апреля 2020

Вы можете использовать reduce() метод для массива с Object.values для дубликатов фильтра

const inputArray = [
    {id: 'id_one', value: 'value_one', label: 'ABC'},
    {id: 'id_one', value: 'value_one', label: 'ABC'},
    {id: 'id_three', value: 'value_three', label: 'ABX'},
    {id: 'id_two', value: 'value_two', label: 'ABY'},
    {id: 'id_four', value: 'value_four', label: 'ABD'}
    ]


      
const filterArray = (arr) => Object.values(arr.reduce(
  (acum, item) => {
    acum[item.id] = item
    return acum
  }, 
  {})
)

console.log(filterArray(inputArray))
0 голосов
/ 03 апреля 2020

Вы можете сделать это, сохраняя id в object и проверяя, существует ли id в object. Если существует, это означает, что вы взяли объект раньше. Если нет, то pu sh объект в новый массив.

Этот подход занимает O(n) время, когда мы проверяем объект с постоянным временем.

var arr = [
    {id: 'id_one', value: 'value_one', label: 'ABC'},
    {id: 'id_one', value: 'value_one', label: 'ABC'},
    {id: 'id_three', value: 'value_three', label: 'ABX'},
    {id: 'id_two', value: 'value_two', label: 'ABY'},
    {id: 'id_four', value: 'value_four', label: 'ABD'}
];


function getDistValues(arr) {
	var hash = {};
    var uniqueArr = [];
    
	for (var i = 0, l = arr.length; i < l; i++) {
    	    if (hash[arr[i].id] === undefined) {
        	hash[arr[i].id] = 1;
                uniqueArr.push(arr[i]);
            }	
        }
    
    return uniqueArr;
}

console.log(getDistValues(arr));
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 03 апреля 2020

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

Вы должны инвертировать это - проверить, существует ли элемент , а затем добавить его в tempIndex

var data = [
  {id: "id_one", value: "value_one", label: "ABC"},
  {id: "id_one", value: "value_one", label: "ABC"},
  {id: "id_three", value: "value_three", label: "ABX"},
  {id: "id_two", value: "value_two", label: "ABY"},
  {id: "id_four", value: "value_four", label: "ABD"}
];

function getDistValues(object) {
  var distObject = [];
  var tempIndex = [];
  var length = object.length;

  for (var i = 0; i < length; i++) {
    //check first
    var notSeen = tempIndex.indexOf(object[i].id) === -1;
    
    if (notSeen) {
      tempIndex.push(object[i].id);
      //add later
      distObject.push(object[i]);
    }
  }

  return distObject;
}

var result = getDistValues(data);

console.log(result);

Чтобы быть более эффективным, вы также можете использовать объект для хранения повторяющихся идентификаторов, что избавит от необходимости повторения над tempIndex каждые l * 1024. *:

var data = [
  {id: "id_one", value: "value_one", label: "ABC"},
  {id: "id_one", value: "value_one", label: "ABC"},
  {id: "id_three", value: "value_three", label: "ABX"},
  {id: "id_two", value: "value_two", label: "ABY"},
  {id: "id_four", value: "value_four", label: "ABD"}
];

function getDistValues(object) {
  var distObject = [];
  //use object
  var tempIndex = {};
  var length = object.length;

  for (var i = 0; i < length; i++) {
    var notSeen = tempIndex[object[i].id] !== true;
    
    if (notSeen) {
      //mark as visited
      tempIndex[object[i].id] = true;
      distObject.push(object[i]);
    }
  }

  return distObject;
}

var result = getDistValues(data);

console.log(result);
0 голосов
/ 03 апреля 2020

Вот решение с использованием приведения и объекта

const input = [
{id: 'id_one', value: 'value_one', label: 'ABC'},
{id: 'id_one', value: 'value_one', label: 'ABC'},
{id: 'id_three', value: 'value_three', label: 'ABX'},
{id: 'id_two', value: 'value_two', label: 'ABY'},
{id: 'id_four', value: 'value_four', label: 'ABD'}
]

const output = Object.values(
  input.reduce((memo, curr) => {
    memo[curr.id] = curr
    return memo
  }, {})
)

console.log(output)
...