Дедупликация массива массивов в javascript - PullRequest
0 голосов
/ 12 июля 2020

Я хочу дедуплицировать массив массивов. Дублирующий массив - это массив, который соответствует подмножеству индексов элементов. В этом случае, скажем, индекс [1] и индекс [3].

const unDeduplicated = [
  [ 11, 12, 13, 14, 15, ],
  [ 21, 22, 23, 24, 25, ],
  [ 31, 88, 33, 99, 35, ], // duplicate in indices: 1, 3 with row index 4
  [ 41, 42, 43, 44, 45, ],
  [ 51, 88, 53, 99, 55, ], // duplicate in indices: 1, 3 // delete this row from result
];

const deduplicated = getDeduplicated( unDeduplicated, [ 1, 3, ], );

console.log( deduplicated );
// expected result:
// [
//   [ 11, 12, 13, 14, 15, ],
//   [ 21, 22, 23, 24, 25, ],
//   [ 31, 88, 33, 99, 35, ],
//   [ 41, 42, 43, 44, 45, ],
//   // this row was omitted from result because it was duplicated at indices 1 and 3 with row index 2
// ]

Какая функция getDeduplicated() может дать мне такой результат?

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

/**
 * Returns deduplicated array as a data grid ([][] -> 2D array)
 * @param { [][] } unDedupedDataGrid The original data grid to be deduplicated to include only unque rows as defined by the indices2compare.
 * @param { Number[] } indices2compare An array of indices to compare for each array element.
 * If every element at each index for a given row is duplicated elsewhere in the array,
 * then the array element is considered a duplicate
 * @returns { [][] }
 */
const getDeduplicated = ( unDedupedDataGrid, indices2compare, ) => {
  let deduped = [];
  unDedupedDataGrid.forEach( row => {
    const matchedArray = a.filter( row => row[1] === 88 && row[3] === 99 );
    const matchedArrayLength = matchedArray.length;
    if( matchedArrayLength ) return;
    deduped.push( row, );
  });
}

Я исследовал некоторые функции loda sh, которые могут помочь, например, _.filter и _.some, но пока я могу Кажется, не удалось найти структуру, которая дает желаемый результат.

Ответы [ 5 ]

2 голосов
/ 12 июля 2020

Вы можете создать Set из значений в столбцах при итерации по строкам. Вы можете создать наборы только для указанных столбцов, например, 1 и 3 в вашем случае. Затем при итерации по каждой строке вы проверяете, имеет ли какой-либо из обозначенных столбцов в этой строке такое значение, которое уже находится в соответствующем наборе, и если да, вы отбрасываете эту строку.

(На телефоне невозможно ввести реальный код. И я думаю, код тоже довольно прост)

1 голос
/ 12 июля 2020

Вероятно, это не самый эффективный алгоритм, но я бы сделал что-то вроде

function getDeduplicated(unDeduplicated, idxs) {
  const result = [];
  const used = new Set();
  unDeduplicated.forEach(arr => {
    const vals = idxs.map(i => arr[i]).join();
    if (!used.has(vals)) {
      result.push(arr);
      used.add(vals);
    }
  });

  return result;
}
0 голосов
/ 12 июля 2020

Это довольно кратко. Он использует вложенные фильтры. Он также будет работать для любого количества дубликатов, сохраняя только первый.

init = [
  [ 11, 12, 13, 14, 15],
  [ 21, 22, 23, 24, 25],
  [ 31, 88, 33, 99, 35],
  [ 41, 42, 43, 44, 45],
  [ 51, 88, 53, 99, 55],
];

var deDuplicate = function(array, indices){
var res = array.filter(
  (elem) => !array.some(
  (el) =>
  array.indexOf(el) < array.indexOf(elem) && //check that we don't discard the first dupe
  el.filter((i) => indices.includes(el.indexOf(i))).every((l,index) => l === elem.filter((j) => indices.includes(elem.indexOf(j)))[index])
//check if the requested indexes are the same.
// Made a bit nasty by the fact that you can't compare arrays with ===
  )
);
return(res);
}
console.log(deDuplicate(init,[1,3]));
0 голосов
/ 12 июля 2020

Не самый эффективный, но это удалит дублирование более чем одного повторяющегося массива

const unDeduplicated = [ [ 11, 12, 13, 14, 15, ], [ 21, 22, 23, 24, 25, ], [ 31, 88, 33, 99, 35, ], [ 41, 33, 43, 44, 45, ], [ 51, 88, 53, 99, 55, ]]
const unDeduplicated1 = [
  [ 11, 12, 13, 14, 15, ],
  [ 21, 22, 23, 24, 25, ],// duplicate in indices: 1, 3 with row index 3
  [ 31, 88, 33, 99, 35, ], // duplicate in indices: 1, 3 with row index 4
  [ 21, 22, 43, 24, 45, ],// duplicate in indices: 1, 3 // delete this
  [ 51, 88, 53, 99, 55, ], // duplicate in indices: 1, 3 // delete this row from result
];
function getDeduplicated(arr, arind) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 1 + i; j < arr.length; j++) {
      if (arr[j].includes(arr[i][arind[0]]) && arr[j].includes(arr[i][arind[1]])) {
        arr.splice(j, 1)
        i--
      } else continue
    }
  }
  return arr
}
const deduplicated = getDeduplicated(unDeduplicated, [1, 3]);
const deduplicated2 = getDeduplicated(unDeduplicated1, [1, 3]);

console.log(deduplicated)
console.log("#####################")
console.log(deduplicated2)
0 голосов
/ 12 июля 2020

Идентификатор, если я хорошо понимаю, что вы хотите сделать, но вот что я сделал

list = [
  [ 11, 12, 13, 14, 15, ],
  [ 21, 22, 23, 24, 25, ],
  [ 21, 58, 49, 57, 28, ],
  [ 31, 88, 33, 88, 35, ],
  [ 41, 42, 43, 44, 45, ],
  [ 51, 88, 53, 88, 55, ],
  [ 41, 77, 16, 29, 37, ],
];

el_list = []  // Auxiliar to save all unique numbers
res_list = list.reduce(
    (_list, row) => {
        // console.log(_list)
        this_rows_el = []  // Auxiliar to save this row's elements
        _list.push(row.reduce(
            (keep_row, el) => {
                // console.log(keep_row, this_rows_el, el)
                if(keep_row && el_list.indexOf(el)==-1 ){
                    el_list.push(el)
                    this_rows_el.push(el)
                    return true
                }else if(this_rows_el.indexOf(el)!=-1) return true  // Bypass repeated elements in this row
                else return false
            }, true) ? row : null)  // To get only duplicated rows (...) ? null : row )
        return _list
    }, []
)

console.log(res_list)
...