find unique items in a set of arrays and remove non-uniques from arrays found
Givven an object with Key as an Array (of position) and Value as an Array as well:
// Example Object
0,2 : [6, 8, 9]
0,3 : [1, 6, 开发者_运维技巧8]
0,4 : [6, 8]
0,5 : [6, 8]
0,6 : [4, 5, 8, 9]
0,7 : [5, 8]
0,8 : [4, 5, 7, 9]
(it was created like this:
x = {};
x[[0,2]] = [6, 8, 9];
x[[0,3]] = [1, 6, 8];
...
Now, I want to narrow down my object to this, by checking if any number in an Array appears only inside this array, and not in others value's arrays, then eliminating all the other numbers inside the specific array which holds the unique number.
(Rule: no duplicated inside a given array, so no need to check that):// Result Object
0,2 : [6, 8, 9]
0,3 : [1]
0,4 : [6, 8]
0,5 : [6, 8]
0,6 : [4, 5, 8, 9] // now 4 becomes also a "loner"
0,7 : [5, 8]
0,8 : [7]
so here in Key [0,3] the Value's array was narrowed down to just [1] because 1 is a unique number not showing up in the other array.
I'm having trouble thinking of an efficient pattern for this...
Don't understand why 0,4 is [6, 8]. Both 6 and 8 have already appeared in 0,2 : [6, 8, 9].
u = [];
$.each(x, function(i, arr){
//console.log(arr);
x[i] = $.grep(arr, function(elem, i){
return ($.inArray(elem, u) == -1);
});
$.merge(u, arr);
});
Demo
Object x is modified with result of
0,2: [6, 8, 9]
0,3: 1
0,4: []
0,5: []
0,6: [4, 5]
0,7: []
0,8: [7]
$.each(x, function(i, arr){
u = [];
$.each(x, function(j, arrJ){
$.merge(u, i == j ? [] : arrJ);
});
var ue = null;
$.each(arr, function(i, elem){
if ($.inArray(elem, u) == -1) {
ue = elem;
}
});
if (ue != null){
arr.length = 0;
arr[0] = ue;
}
});
Demo
the idea is to use buckets, consider this a fun experiment, and i know the code can be optimized, and not so pretty, but it solves the problem, and it's not that inefficient:
var x = {}; // object
x[[0,2]] = [6, 8, 9];
x[[0,3]] = [1, 6, 8];
x[[0,4]] = [6, 8];
x[[0,5]] = [6, 8];
x[[0,6]] = [4, 5, 8, 9];
x[[0,7]] = [5, 8];
x[[0,8]] = [4, 5, 7, 9];
var trackCount = [];
for(var key in x){
for(var j in x[key]){
// console.log(key);
if(typeof(trackCount[x[key][j]]) === "undefined"){
trackCount[x[key][j]] = [];
}
// trackCount[x[key][j]].push(trackCount[x[key]]);
trackCount[x[key][j]].push(key);
}
}
//console.log(trackCount)
for(var i=0;i<trackCount.length;++i){
if(trackCount[i] && trackCount[i].length == 1){
x[trackCount[i][0]] = [];
x[trackCount[i][0]].push(i)
}
}
console.log(x);
Long-winded Approach (jsfiddle)
var sudoku = { '0,2' : [6,8,9]
, '0,3' : [1,6,8]
, '0,4' : [6,8]
, '0,5' : [6,8]
, '0,6' : [4,5,8,9]
, '0,7' : [5,8]
, '0,8' : [4,5,7,9]
};
var finished = false;
while (!finished) {
var unique = {};
finished = true;
// Build Unique Numbers List
for (var section in sudoku)
for (var pos = sudoku[section].length; pos--; ){
if (typeof unique[ sudoku[section][pos] ] === "undefined")
unique[ sudoku[section][pos] ] = [];
unique[sudoku[section][pos]].push(section);
}
// Clean Up Unique Numbers List
for (var num in unique)
if (unique[num].length > 1)
delete unique[num];
// Remove non-Uniques
var is_unique = false;
for ( var num in unique )
for ( var pos = sudoku[ unique[num] ].length; pos--; ){
is_unique = false;
for (var unique_value in unique)
if (sudoku[ unique[num] ][pos] == unique_value){
is_unique = true;
break;
}
if (!is_unique){
sudoku[ unique[num] ].splice(pos,1);
finished = false;
}
}
}
console.clear();
console.dir(unique);
console.dir(sudoku);
/**/
Result
{sudoku}
[0,2] : [9]
[0,3] : [1]
[0,4] : [6, 8]
[0,5] : [6, 8]
[0,6] : [4]
[0,7] : [5]
[0,8] : [7]
Note: This is not the most optimized algorithm to use, but since this is for Sudoku, performance won't really be impacted by any algorithm you choose. So, I'd choose amit_g's jQuery solution for conciseness. Otherwise, the above should do well for both explanation and accuracy.
Edit: This has been modified to recursively filter the results.
I would create a separate single dimension array that keeps track of the values in the multi-dimensional array.
Iterate through each value in the multi-dimensional array. If the value doesn't exist in the single-dimension array, add it to the single dimension array and keep it in the multi-dimension array. If the value DOES exist in the single-dimension array, just remove it from the multi-dimension array and move on to the next value.
The idea here it that i go through every number in every array, and check it against
a Bucket (string) which holds all the numbers from all the arrays, joined. if the first index of the current x[key][i]
in the bucket is the SAME as the last index, it means this number is unique and, thus it's holding array is reset to hold that number alone.
var x = {}; // object
x[[0,0]] = [6, 8, 9];
x[[0,1]] = [1, 6, 8];
x[[0,2]] = [6, 8];
x[[0,3]] = [6, 8];
x[[0,4]] = [4, 5, 8, 9];
x[[0,5]] = [5, 8];
x[[0,6]] = [4, 5, 7, 9];
function findUniquePosibilites(x){
var bucket = "";
for(var key in x)
bucket += x[key].join("");
for(var key in x)
for (var i = x[key].length; i--; ){
var num = x[key][i];
if( bucket.indexOf(num) == bucket.lastIndexOf(num) ){
x[key] = [num];
break;
};
}
}
findUniquePosibilites(x);
console.dir( x );
/*
0,0 : [6, 8, 9]
0,1 : [1]
0,2 : [6, 8]
0,3 : [6, 8]
0,4 : [4, 5, 8, 9]
0,5 : [5, 8]
0,6 : [7]
*/
精彩评论