-2

I have this data, how can I return unique array - an array that doesn't have duplicate for every index.

[ 
  [ 0, 1, 2 ], 
  [ 1, 0, 2 ], 
  [ 1, 1, 1 ], 
  [ 1, 2, 0 ], 
  [ 2, 0, 1 ], 
  [ 2, 1, 0 ] 
]

my desired output would be like this
0 1 2
1 2 0
2 0 1

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
Jiel
  • 103
  • 1
  • 2
  • 12
  • 1
    Possible duplicate of [Get all unique values in a JavaScript array (remove duplicates)](https://stackoverflow.com/questions/1960473/get-all-unique-values-in-a-javascript-array-remove-duplicates) – LocoGris Mar 05 '19 at 09:34
  • You have to make your wish a little bit clearer. I don't understand what you mean by 'doesn't have duplicate for every index' – yunzen Mar 05 '19 at 09:40
  • @yunzen example: [ [0, 1, 2], [1, 0 , 2], [2, 0, 1] ] first and second array is duplicate because its third index is both 2, so how would you return first and third array only? – Jiel Mar 05 '19 at 09:42
  • 1
    please add your try and the last comment to the question. – Nina Scholz Mar 05 '19 at 09:51
  • @NinaScholz finds that The OP uniqueness-task has many solutions e.g. for [1,0,0],[0,1,1],[0,2,2] we have two solutions: A [1,0,0],[0,1,1], B [1,0,0],[0,2,2]. However the question/problem is still valid – Kamil Kiełczewski Mar 05 '19 at 15:18
  • @KamilKiełczewski, no i don't think so. but the answer below are highly dependent of the order of the arrays. i would add an answer if i could, but the question is still closed. – Nina Scholz Mar 05 '19 at 15:20
  • @KamilKiełczewski most of the answers actually helped, thank you.. – Jiel Mar 06 '19 at 05:41

4 Answers4

2

This should be, what you want.

console.clear()
arr = [ 
  [ 0, 1, 2 ], 
  [ 1, 0, 2 ], 
  [ 1, 1, 1 ], 
  [ 1, 2, 0 ], 
  [ 2, 0, 1 ], 
  [ 2, 1, 0 ] 
];

var res = arr.filter((duplicates = [], e => {
  // prefill duplicates with empty arrays
  e.forEach((k, i) => {
    duplicates[i] = duplicates[i] ||  [];
  })
  // check if there are duplicates and then set keep to false
  let keep = e.reduce((keep, val, i) => {
    return keep && (!duplicates[i].includes(val));
  }, true);
  // if keep, save this array to duplicates
  if (keep) {
    e.forEach((k, i) => {
      duplicates[i].push(k)
    })
  }
  return keep;
}))

res.forEach(k => {
  console.log(...k)
})
.as-console-wrapper { max-height: 100% !important; top: 0; }
yunzen
  • 32,854
  • 11
  • 73
  • 106
  • i like this answer, but the result is highly dependent of the order of the arrays. – Nina Scholz Mar 05 '19 at 14:29
  • @NinaScholz It always will be – yunzen Mar 05 '19 at 15:18
  • @NinaScholz Just take `(1 1), (1 2), (0 2)` as an example. The first is always used, the second is thrown away, because `(1 1)` already has a `1` at first position, `(0 2)` is used, because no duplicate. Result is `(1 1), (0 2)` – yunzen Mar 05 '19 at 15:33
  • @NinaScholz Now change the order `(1 2), (1 1), (0 2)`. I swapped 1st and 2nd. First is always used. Second is thrown away and last is also thrown away. Result is `(1 2)` – yunzen Mar 05 '19 at 15:35
  • right. should it be dependent on the order? i don't think so. – Nina Scholz Mar 05 '19 at 15:35
  • @NinaScholz That's what the asker described in the OP. – yunzen Mar 05 '19 at 15:37
  • @NinaScholz look [here](https://stackoverflow.com/a/55011800/860099) - finding the largest unique subset is probably NP-hard problem. However question about finding the smalest unique subset is open... The OP in question don't give restrictions about which solution he want - so algorithm which find any solution (because usually there are many solutions) is acceptable. – Kamil Kiełczewski Mar 06 '19 at 04:45
  • @NinaScholz according to [this](https://cstheory.stackexchange.com/questions/42492/3-dimensional-matching-shortest-solution-np-hard/42493#42493) finding shortest solution is also NP-hard – Kamil Kiełczewski Mar 08 '19 at 11:37
  • @KamilKiełczewski, anyway, the question is cloded. – Nina Scholz Mar 08 '19 at 11:41
1

try

let a= [ [0,1,2], [1,0,2], [1,1,1], [1,2,0 ], [2,0,1 ], [2,1,0 ] ];

let t=[{},{},{}];

let d= a.filter(e => 
  !e.reduce((g,h,i)=> g||(e[i] in t[i]),false) && e.map((x,i) => t[i][x]=x)
);

console.log(JSON.stringify(d));

Update

The OP uniqueness-task can have more than one solution (what was mention by @NinaSholz in comments to this answer) - e.g. for OP example we have at least two independent unique (in sense describe by OP) solutions:

  • [0,1,2],[1,2,0],[2,0,1]
  • [1,0,2],[2,1,0]

What is interesting in OP example is that both solutions have different number of elements - I ask new question about find optimal solution (shortest or longest) here.

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
1

Try this

let arr= [ [ 0, 1, 2 ], [ 1, 0, 2 ], [ 1, 1, 1 ], [ 1, 2, 0 ], [ 2, 0, 1 ], [ 2, 1, 0 ] ];

let index =[];
arr.forEach(function(element) {
  element.forEach(function (value, i) {
    if(index[i] == undefined)
    {
      var x = [value];
      index[i]= x;
    }
    else if (index[i].indexOf(value) ==-1)
    {
      index[i].push(value);
    }
  });
});
index.forEach(k => {
  console.log(...k)
})
Mohammad Ali Rony
  • 4,695
  • 3
  • 19
  • 33
0

This solution is checking for all the elements of each array in one loop, if you have three elements in each array(as you show) then this solution should work for you.

var arr = [ 
  [ 0, 1, 2 ], 
  [ 1, 0, 2 ], 
  [ 1, 1, 1 ], 
  [ 1, 2, 0 ], 
  [ 2, 0, 1 ], 
  [ 2, 1, 0 ] 
]

var indicesToRemove = arr.reduce((acc, eachElem, index) => {
  var isRemoveIndexPushed = false;
  if (acc.firstIndex.length !== 0 && acc.firstIndex.indexOf(eachElem[0]) != -1) {
    isRemoveIndexPushed = true
  }
  
  if (acc.secondIndex.length !==0 && acc.secondIndex.indexOf(eachElem[1]) != -1) {
    isRemoveIndexPushed = true;
  }
  
  
  if (acc.thirdIndex.length !== 0 && acc.thirdIndex.indexOf(eachElem[2]) != -1) {
    isRemoveIndexPushed = true
  } 
  
  if (!isRemoveIndexPushed) {
    acc.firstIndex.push(eachElem[0]);
    acc.secondIndex.push(eachElem[1]);
    acc.thirdIndex.push(eachElem[2]);
  } else {
    acc.removeIndex.push(index);
  }
  
  return acc;

  
}, {removeIndex: [], firstIndex: [], secondIndex: [], thirdIndex: []}).removeIndex;


var newArr = []
arr.forEach((elem, i) => {
  if (i === indicesToRemove[0]) {
    indicesToRemove.shift()
  } else {
    newArr.push(elem)
  }
})

arr = newArr
console.log(arr)
Ashish Ranjan
  • 12,760
  • 5
  • 27
  • 51