Compare javascript array of array by distinct values - javascript

Following code i wanted to share which compares two array of array:-
var x = [["x", "r", "t"], ["a", "b", "n"], ["j", "l", "x"]];
var y = [["y", "w", "z"], ["a", "b", "n"], ["j", "l", "x"]];
var objX = [];
var objY = [];
for (var i = 0; i < x.length; i++)
{
objX[i] = {};
for (var j = 0; j < x[i].length; j++)
{
objX[i][x[i][j]] = i;
}
}
for (var i = 0; i < y.length; i++)
{
objY[i] = {};
for (var j = 0; j < y[i].length; j++)
{
objY[i][y[i][j]] = i;
}
}
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key))
size++;
}
return size;
};
function compareObjs(oA, oB)
{
if (Object.size(oA) > Object.size(oB))
{
aa = oA;
ba = oB;
}
else
{
aa = oB;
ba = oA;
}
for (var property in aa) {
if (!ba.hasOwnProperty(property)) {
return false;
}
}
return true;
}
function compareArrayOfObj(aA, aB)
{
var aIb = [];
var aMb = [];
var bMa = [];
var aIIndex = [];
var bIIndex = [];
var aIF = [];
var bIF = [];
if (aA.length > aB.length)
{
a = aA;
b = aB;
}
else
{
a = aB;
b = aA;
}
for (var i in a)
{
for (var j in b)
{
if (compareObjs(a[i], b[j]))
{
for (var blah in a[i])
{
aIb.push(x[a[i][blah]]);
break;
}
aIIndex.push(i);
bIIndex.push(j);
}
}
}
for (var i in a)
{
if (aIIndex.indexOf(i) == -1)
{
for (var blah in a[i])
{
aIF.push(x[a[i][blah]]);
break;
}
}
}
for (var j in b)
{
if (bIIndex.indexOf(j) == -1)
{
for (var blah in b[j])
{
bIF.push(y[b[j][blah]]);
break;
}
}
}
return {"aIb": aIb, "aMb": aIF, "bMa": bIF}
}
resultSet=compareArrayOfObj(objX, objY);
/*
resultSet object holds three properties as:-
1. aIb = objX Intersection objY
2. aMb = objX - objY
3. bMa = objY - objX
*/
Improvisation in the code is always welcome.
Basically i have written this code to have set operation on arrays.
It will return A minus B,B minus A and A intersection B.

Related

Where has my logic gone wrong in my attempt to implement a sudoku solver in Javascript?

const N = 4;
const fourbyfour = [
[1, 0, 0, 4],
[3, 4, 1, 2],
[2, 1, 4, 3],
[4, 3, 2, 1],
];
function solve(board) {
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
if (board[i][j] === 0) {
for (let k = 1; k < N + 1; k++) {
board[i][j] = k;
if (isValidBoard(board)) {
if (isSolved(board)) return board;
else solve(board);
}
}
}
}
}
return;
}
function isSolved(board) {
let cells = [];
for (let row of board) {
cells.push(...row);
}
return !cells.includes(0);
}
function isValidBoard(board) {
// Check rows are valid
for (let i = 0; i < N; i++) {
const row = board[i].filter((cell) => cell !== 0);
if (new Set(row).size !== row.length) {
return false;
}
}
// Check columns are valid
for (let i = 0; i < N; i++) {
let column = [];
for (let j = 0; j < N; j++) {
if (board[j][i] !== 0) column.push(board[j][i]);
}
if (new Set(column).size !== column.length) {
return false;
}
}
const root = Math.sqrt(N);
// Check each grid
for (let i = 0; i < N; i += root) {
for (let j = 0; j < N; j += root) {
const square = [];
for (let k = i; k < i + root; k++) {
for (let l = j; l < j + root; l++) {
if (board[k][l] !== 0) {
square.push(board[k][l]);
}
}
}
if (new Set(square).size !== square.length) {
return false;
}
}
}
return true;
}
console.table(solve(fourbyfour));
solve() keeps on returning undefined.
I'm fairly certain the issue is in the solve function, and not related to isSolved() and isValidBoard(). The solve function is getting the correct board, if I console.log the board instead of returning it, the correct board gets printed, but for some reason it isn't getting returned.
You are never returning the value of your recursion. You need to return from the second time you enter solve.
Also, console.table does not seams to be working in the snippet
const N = 4;
const fourbyfour = [
[1, 0, 0, 4],
[3, 4, 1, 2],
[2, 1, 4, 3],
[4, 3, 2, 1],
];
function solve(board) {
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
if (board[i][j] === 0) {
for (let k = 1; k < N + 1; k++) {
board[i][j] = k;
if (isValidBoard(board)) {
if (isSolved(board)) {
return board;
} else {
return solve(board);
}
}
}
}
}
}
return 'test';
}
function isSolved(board) {
let cells = [];
for (let row of board) {
cells.push(...row);
}
return !cells.includes(0);
}
function isValidBoard(board) {
// Check rows are valid
for (let i = 0; i < N; i++) {
const row = board[i].filter((cell) => cell !== 0);
if (new Set(row).size !== row.length) {
return false;
}
}
// Check columns are valid
for (let i = 0; i < N; i++) {
let column = [];
for (let j = 0; j < N; j++) {
if (board[j][i] !== 0) column.push(board[j][i]);
}
if (new Set(column).size !== column.length) {
return false;
}
}
const root = Math.sqrt(N);
// Check each grid
for (let i = 0; i < N; i += root) {
for (let j = 0; j < N; j += root) {
const square = [];
for (let k = i; k < i + root; k++) {
for (let l = j; l < j + root; l++) {
if (board[k][l] !== 0) {
square.push(board[k][l]);
}
}
}
if (new Set(square).size !== square.length) {
return false;
}
}
}
return true;
}
console.log(solve(fourbyfour));

JavaScript Refactor From Two to Many Function Arguments

These two JavaScript functions each accept TWO array arguments and return ONE array result. Conforming to ES3, how can I rewrite these to accept an indefinite number of array inputs?
function sum(v, w) {
for (var a = jsArray(v), b = jsArray(w), t = 0; t < a.length; t++) a[t] += b[t];
return vbArray(a);
}
function mul(v, w) {
for (var a = jsArray(v), b = jsArray(w), t = 0; t < a.length; t++) a[t] *= b[t];
return vbArray(a);
}
The odd jsArray() function is required because the arrays to be processed are coming from VBA and jsArray() converts them to JavaScript arrays:
function jsArray(v) {
return new VBArray(v).toArray()
}
You can try to use array-like object arguments in order to get all passed arguments:
function someFunc() {
for (var i=0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
someFunc('a', 'b', 'c');
Example of transformed sum function. Beware that this works if all the passed arrays have the same length.
function sum() {
var arrays = [];
for (var i = 0; i < arguments.length; i++) {
arrays[i] = jsArray(arguments[i]);
}
for (var j = 1; j < arrays.length; j++) {
for (var t = 0; t < arrays[0].length; t++) {
arrays[0][t] += arrays[j][t];
}
}
return vbArray(arrays[0]);
}
Generalized solution:
function process(concreteFunc) {
var arrays = [];
for (var i = 1; i < arguments.length; i++) {
arrays.push(jsArray(arguments[i]));
}
for (var j = 1; j < arrays.length; j++) {
for (var t = 0; t < arrays[0].length; t++) {
arrays[0][t] = concreteFunc(arrays[0][t], arrays[j][t]);
}
}
return vbArray(arrays[0]);
}
var sum = process.bind(null, function (a, b) {return a + b});
var mul = process.bind(null, function (a, b) {return a * b});
Solution without .bind:
function process(concreteFunc, args) {
var arrays = [];
for (var i = 0; i < args.length; i++) {
arrays.push(jsArray(args[i]));
}
for (var j = 1; j < arrays.length; j++) {
for (var t = 0; t < arrays[0].length; t++) {
arrays[0][t] = concreteFunc(arrays[0][t], arrays[j][t]);
}
}
return vbArray(arrays[0]);
}
function createFunc(handler) {
return function() {
return process(handler, Array.prototype.slice.call(arguments));
}
}
var sum = createFunc(function (a, b) {return a + b});
var mul = createFunc(function (a, b) {return a * b});
Improved version to support ability to implement avg:
function process(concreteFunc, args) {
var arrays = [];
for (var i = 0; i < args.length; i++) {
arrays.push(jsArray(args[i]));
}
var result = [];
for (var j = 0; j < arrays[0].length; j++) {
var items = [];
for (var t = 0; t < arrays.length; t++) {
items.push(arrays[t][j]);
}
result.push(concreteFunc(items));
}
return vbArray(result);
}
function createFunc(handler) {
return function() {
return process(handler, Array.prototype.slice.call(arguments));
}
}
function reduce(items, handler) {
var result = items[0];
for (var i = 1; i < items.length; i++) {
result = handler(result, items[i]);
}
return result;
}
var sum = createFunc(function(items) {
return reduce(items, function (a, b) {return a + b});
});
var mul = createFunc(function(items) {
return reduce(items, function (a, b) {return a * b});
});
var avg = createFunc(function(items) {
return reduce(items, function (a, b) {return a + b}) / items.length;
});

find number of string matches from array to array in javascript?

I need to find number of strings in array b that contains in array arr. I got the output but i need it in this order.[[3,6,0],[1,3,1]]
here my code goes.
var arr = [["00","00","00","01","01","01","01","01","01"],["000","100","01","01","01"]];
var b = ["00","01",10];
var cc = [];
for (var i=0;i<b.length;i++) {
var k = [];
for (var y=0;y<arr.length;y++) {
var a = 0;
for (var x=0;x<arr[y].length;x++) {
if ((arr[y][x].substring(0,2)).indexOf(b[i]) != -1) {
a++;
}
}
k.push(a)
}
cc.push(k);
}
console.log(JSON.stringify(cc));// output :[[3,1],[6,3],[0,1]]
Actual output : [[3,1],[6,3],[0,1]]
Expected output : [[3,6,0],[1,3,1]]
I want the result either in javascript or jquery.
As you have in b number 10 you need convert it to String and then search in array, because arr contains only strings
var arr = [
["00","00","00","01","01","01","01","01","01"],
["000","100","01","01","01"]
];
var b = ["00", "01", 10];
var len, i, j, key, result = [], counts = [], count = 0;
for (i = 0, len = arr.length; i < len; i++) {
for (j = 0; j < b.length; j++) {
count = 0;
key = String(b[j]);
count = arr[i].filter(function (el) {
return el.slice(0, 2) === key;
}).length;
counts.push(count);
}
result.push(counts);
counts = [];
}
console.log(JSON.stringify(result));
Version for IE < 9, where there is not .filter method
var arr = [
["00","00","00","01","01","01","01","01","01"],
["000","100","01","01","01"]
];
var b = ["00", "01", 10];
var len,
key,
result = [],
counts = [],
i, j, k, count;
for (i = 0, len = arr.length; i < len; i++) {
for (j = 0; j < b.length; j++) {
count = 0;
key = String(b[j]);
for (k = 0; k < arr[i].length; k++) {
if (arr[i][k].slice(0, 2) === key) {
count++;
}
}
counts.push(count);
}
result.push(counts);
counts = [];
}
console.log(JSON.stringify(result));
Seems like there are some typo in your sample input. Following code may help.
var arr = [["00","00","00","01","01","01","01","01","01"],["00","10","01","01","01"]];
var b = ["00","01","10"];
var cc = [];
arr.forEach(function(ar,i){
cc[i] = [];
b.forEach(function(a,j){
cc[i][j] = ar.filter(function(d){ return d==a }).length;
});
});
alert(JSON.stringify(cc));
Or
var arr = [
["00", "00", "00", "01", "01", "01", "01", "01", "01"],
["00", "10", "01", "01", "01"]
];
var b = ["00", "01", "10"];
var cc = arr.map(function(ar) {
return b.map(function(a) {
return ar.filter(function(d) {
return d == a
}).length;
})
});
alert(JSON.stringify(cc));

Return Sorted Array Without Modifying Original Array

I'm having trouble with a function returning the original array as opposed to the sorted array. I tried to slice the array and return the sorted but it is not working. Any ideas on how to fix this?
function sortArr( comparator, array ){
var newArray = array.slice();
for(var i = 0; i < newArray.size; i++)
{
var min = i;
for(var x = i; x < newArray.size; x++)
{
if(comparator(newArray[min],newArray[x]) == true)
{
min = x;
}
}
var temp = newArray[i];
newArray[i] = newArray[min];
newArray[min] = temp;
}
return newArray;
}
I fixed the function:
function sortArr( comparator, array ){
/*your code here*/
var i, x;
var min;
var newArray = array.slice();
for(i = 0; i < newArray.length - 1; i++)
{
min = i;
for(x = i + 1; x < newArray.length; x++)
{
if(comparator(newArray[min],newArray[x]) == true)
{
min = x;
}
}
if(min != i){
var temp = newArray[i];
newArray[i] = newArray[min];
newArray[min] = temp;
}
}
return newArray;
}
Copy the array with slice and then use native sort:
function sortArr(comparator, array) {
return array.slice().sort(function(a,b) {
return comparator(a,b) * 2 - 1;
});
}
Your sorting algorithm doesn't look quite right. For a start the swapping of values should be inside the if statement. I would also advise to look at #Oriol's solution which is far more elegant.
function sortArr( comparator, array ){
var newArray = array.slice();
for(var i = 0; i < newArray.size; i++)
{
var min = i;
for(var x = i; x < newArray.size; x++)
{
if(comparator(newArray[min],newArray[x]) == true)
{
var temp = newArray[i];
newArray[i] = newArray[min];
newArray[min] = temp;
min = x;
}
}
}
return newArray;
}
{"index.js":"var globalArray = [5, 6, 3, 2, 9];
function nonMutatingSort(arr) {
let newArr = globalArray.slice();\n let emptyArr = [];
return emptyArr.concat(newArr).sort();
}
nonMutatingSort(globalArray);"}

How to merging javascript arrays and order by position?

Is there anyway to merge arrays in javascript by ordering by index/position. I'm try to accomplish this and haven't been able to find any examples of this.
var array1 = [1,2,3,4]
var array2 = [a,b,c,d]
var array3 = [!,#,#,$]
var merged array = [1,a,!,2,b,#,3,c,#,4,d,$]
I know you can use concat() to put one after the other.
As long as the arrays are all the same length you could just do:
var mergedArray = [];
for (var i = 0, il = array1.length; i < il; i++) {
mergedArray.push(array1[i]);
mergedArray.push(array2[i]);
mergedArray.push(array3[i]);
}
EDIT:
For arrays of varying lengths you could do:
var mergedArray = [];
for (var i = 0, il = Math.max(array1.length, array2.length, array3.length);
i < il; i++) {
if (array1[i]) { mergedArray.push(array1[i]); }
if (array2[i]) { mergedArray.push(array2[i]); }
if (array3[i]) { mergedArray.push(array3[i]); }
}
This should work for arrays of ANY length:
var mergeArrays = function () {
var arr = [],
args = arr.slice.call(arguments),
length = 0;
for (var i = 0, len = args.length; i < len; i++) {
length = args[i].length > length ? args[i].length : length;
}
for (i = 0; i < length; i++) {
for (var j = 0; j < len; j++) {
var value = args[j][i];
if (value) {
arr.push(value);
}
}
}
return arr;
};
Example:
var array1 = [1,2,3,4];
var array2 = ['a','b','c','d','e','f','g','h','i','j','k','l'];
var array3 = ['!','#','#','$','%','^','&','*','('];
mergeArrays(array1, array2, array3);
// outputs: [1, "a", "!", 2, "b", "#", 3, "c", "#", 4, "d", "$", "e", "%", "f", "^", "g", "&", "h", "*", "i", "(", "j", "k", "l"]
This would work also (a little more terse syntax):
var mergeArrays = function () {
var arr = [],
args = arr.slice.call(arguments),
length = Math.max.apply(null, args.map(function (a) { return a.length; }));
for (i = 0; i < length; i++) {
for (var j = 0, len = args.length; j < len; j++) {
var value = args[j][i];
if (value) {
arr.push(value);
}
}
}
return arr;
};
For arrays that are all the same size, where you pass one or more arrays as parameters to merge:
function merge()
{
var result = [];
for (var i=0; i<arguments[0].length; i++)
{
for (var j=0; j<arguments.length; j++)
{
result.push(arguments[j][i]);
}
}
return result;
}
var array1 = ['1','2','3','4'];
var array2 = ['a','b','c','d'];
var array3 = ['!','#','#','$'];
var merged = merge(array1, array2, array3);
Nothing built in, but it wouldn't be hard to manage:
var maxLength = Math.max(array1.length, array2.length, array3.length),
output = [];
for (var i = 0; i < maxLength; i++) {
if (array1[i] != undefined) output.push(array1[i]);
if (array2[i] != undefined) output.push(array2[i]);
if (array3[i] != undefined) output.push(array3[i]);
}
try this...
var masterList = new Array();
var array1 = [1,2,3,4];
var array2 = [a,b,c,d];
var array3 = [!,#,#,$];
for(i = 0; i < array1.length; i++) {
masterList.push(array1[i]);
masterList.push(array2[i]);
masterList.push(array3[i]);
}
It looks like you want to "zip" some number of same-length arrays into a single array:
var zip = function() {
var numArrays=arguments.length
, len=arguments[0].length
, arr=[], i, j;
for (i=0; i<len; i++) {
for (j=0; j<numArrays; j++) {
arr.push(arguments[j][i]);
}
}
return arr;
};
zip([1,2], ['a', 'b']); // => [1, 'a', 2, 'b']
zip([1,2,3], ['a','b','c'], ['!','#','#']); // => [1,'a','#',...,3,'c','#']
If the input arrays could be of different length then you've got to figure out how to deal with that case...
Yes, there is some way to do that. Just:
loop through the larger array,
until at the currently processed position both arrays have elements, assign them one-by-one to the new array,
after the shorter array ends, assign only elements from the longer array,
The resulting array will have the elements ordered by the index from the original arrays. From your decision depends, position in which one of these arrays will have higher priority.
This works for any number of array and with arrays of any length.
function myMerge() {
var result = [],
maxLength = 0;
for (var i = 0; i < arguments.length; i++) {
if (arguments[i].length > maxLength) { maxLength = arguments[i].length; }
}
for (var i = 0; i < maxLength; i++) {
for (var j = 0; j < arguments.length; j++) {
if (arguments[j].length > i) {
result.push(arguments[j][i]);
}
}
}
return result;
}
Eli beat me to the punch up there.
var posConcat = function() {
var arrays = Array.prototype.slice.call(arguments, 0),
newArray = [];
while(arrays.some(notEmpty)) {
for(var i = 0; i < arrays.length; i++) {
if(arguments[i].length > 0)
newArray.push(arguments[i].shift());
}
}
return newArray;
},
notEmpty = function() { return arguments[0].length > 0; };
Usage:
var orderedArray = posConcat(array1,array2,array3);
Sample: http://jsfiddle.net/HH9SR/

Categories