how to iterate array of array in javascript to get common item ? - javascript

/*1 2 3
2 1 3
2 3 1 */
var arr = [
[1,2,3],
[2,1,3],
[2,3,1]
]
function commonElementInColumn(arr){
var a = arr[0],
b=false,
commItem =[];
for(var i=0 ; i<a.length ;i ++){
var item = a[i];
for(j=1; j< arr.length ; j++){
if(arr[j].indexOf(item) !==-1){
b =true
}else {
b= false
}
}
if(b){
commItem.push(item)
}
}
return commItem
}
console.log(commonElementInColumn(arr))
I am trying to find common column item in matrix .I tried like this. But not getting expected output .I am getting [1,2,3] but
can we add any logic which find common element in columns
Expected output is [1]
Let take I have m x n matrix .I want to find common element which is present in all coloum.
See input
/*1 2 3
2 1 3
2 3 1 */
1 is present in all three column.
2 is present only first and second not in third
3 is present on second and third but not in first

Try following
var arr = [
[1,2,3], [2,1,3], [2,3,1]
];
// Create the map of items with value to be an array of indexes
var map = {};
var result = [];
// iterate over the array
arr.forEach(function(subArray){
subArray.forEach(function(item, index){
map[item] = map[item] ? map[item] : [];
// if the map has the item and the index already exists in the array, skip
if(!map[item].includes(index)) {
map[item].push(index);
}
// if the length is same as the array item length (assuming same for all subArray's) then it means all indexes have been covered
if(map[item].length === arr[0].length) {
result.push(item);
}
});
});
console.log(result);

A slightly different approach with a Map for the values and a Set for each value for collecting the indices. Later check the size of the sets and take the keys of the map as result arrray.
function commonCol(array) {
var map = new Map;
array.forEach(a => a.forEach((v, i) => {
if (!map.has(v)) {
map.set(v, new Set);
}
map.get(v).add(i);
}));
return Array
.from(map.entries())
.filter(({ 1: v }) => v.size === array[0].length)
.map(([k]) => k);
}
var array = [[1, 2, 3], [2, 1, 3], [2, 3, 1]];
console.log(commonCol(array));

Take a look at that:
var arr = [
[1,2,3],
[2,1,3],
[2,3,1]
]
// Creates another array from arr organized by column
var byColumn = arr.reduce((accumulator, item) => {
item.forEach((element, index) => {
if(!accumulator[index]) accumulator[index] = [];
accumulator[index].push(element);
});
return accumulator;
}, [])
// Gets the first array of arr to iterate
var firstArray = arr[0];
// Gets an array of elements that appears in all columns
var filteredNumbers = firstArray.filter(element => {
return byColumn.every(item => item.includes(element));
});
console.log(filteredNumbers); // [1]

Use Array#filter() on first subarray since it must contain any common values.
Within that filter use a Set to pass all indices for each number to. Since a Set must have unique values you can then check it's size and if it matches subarray length then all indices are unique
var arr = [
[1, 2, 3],
[2, 1, 3],
[2, 3, 1]
]
function commonElementInColumn(arr) {
// return filtered results from first subarray since it has to contain any common values `
return arr[0].filter((num) => {
// get all indices for this number as array
let indices = arr.map(subArr => subArr.indexOf(num));
//create a set from this array which will void duplicates
let uniqueIndices = new Set(indices);
// if size of set is same as subarray length then all indices for this number are unique
return uniqueIndices.size === arr[0].length;
});
}
console.log(commonElementInColumn(arr))

Related

Get Unique Value Based on Multiple Columns from Spreadsheet using Google Apps Script and JavaScript

So, Basically what I want is to get unique data from a 2d array where I can pass multiple column values which I have stored in an array. Like I want to get unique based on column 1 and 2 so, I can pass the column value like an array [0, 1] to the function and based on the column array it should return unique value.
I have tried something like this:
function sortFunction(a, b) {
if (a[0] === b[0]) { // 0 for column one
return 0;
}
else {
return (a[0] < b[0]) ? -1 : 1;
}
}
function getUniqueData_(arr) {
arr = arr.sort(sortFunction)
let prevEl;
const newArr = arr.reduce((prevArr, currentVal) => {
const idx = prevArr.findIndex(val => val[0] === currentVal[0]);
if (idx === -1) {
if (prevEl && prevEl[0] !== currentVal[0]) {
prevArr.push(currentVal);
}
} else {
prevArr.splice(idx, 1);
}
prevEl = currentVal;
return prevArr;
}, [])
console.log(newArr);
return newArr;
}
Instead of passing column value manually I want to pass it dynamically and multiple columns at the same time which I have stored it in array like [0,1] for column 1 and 2.
Solution:
Use filter to remove the undesired elements from your array.
For each row, use map to get the combination of values related to the columns you want to check, so that if another row exists with this combination, both rows should be filtered out.
For each row, use some to check whether there is another row with this same combination.
Use every to compare both combinations and check they are the same.
Code sample:
function getUniqueData(arr = [[1, 2, 3],[1, 2, 2],[1, 2, 3],[2, 1, 3]], uniqueCols = [0]) {
const uniqueData = arr.filter((currentRow,i) => {
const currentCombo = uniqueCols.map(index => currentRow[index]);
return !arr.some((row,j) => {
const combo = uniqueCols.map(index => row[index]);
return combo.every((c1,k) => c1 === currentCombo[k]) && i !== j;
});
});
return uniqueData;
}
Note:
In the sample above, I added the example you provided in comments data = [[1, 2, 3],[1, 2, 2],[1, 2, 3],[2, 1, 3]] and I want to check unique in column 1 as default parameters. In this case, the returned uniqueData is [2, 1, 3], as expected.
Try this code:
function sortData(){
//change data and column index according to requirements
var columns = [0,2] //0 for column 1
var data = [[1,2,3],[1,2,2],[1,2,3]]
var temp_arr = [];
var unique_arr = []; // for output
var specific_columns_data = getSpecificColumnsData(data, columns) // this function return array according to columns. eg [[1,3],[1,2],[1,3]]
for(var i=0;i<specific_columns_data.length;i++){
if(specific_columns_data[i].join("")!==""){
if(temp_arr.indexOf(specific_columns_data[i].join(""))==-1){
unique_arr.push(data[i]);
}
temp_arr.push(specific_columns_data[i].join(""))
}
}
Logger.log(unique_arr)
}
function getSpecificColumnsData(data, columns){
var specific_columns_data = []
var temp_arr = []
for(var i=0;i<data.length;i++){
temp_arr = []
for(var j = 0;j<columns.length;j++){
if(data[i][j]){
temp_arr.push(data[i][columns[j]])
}
}
specific_columns_data.push([temp_arr])
}
return specific_columns_data;
}
Just in case, here is my variant of the code. It can filter a 2D array by any number of its columns in any given sequence:
var data = [
[1, 2, 3, 4],
[1, 2, 2, 4],
[2, 1, 3, 4],
[3, 1, 2, 4],
[4, 3, 3, 4],
[5, 2, 5, 1],
]
function getUniqueData(data, columns) {
let arr = data.slice();
columns.forEach(c => {
let col = arr.map(x => x[c]);
arr = arr.filter(x => col.indexOf(x[c]) == col.lastIndexOf(x[c]));
});
return arr;
}
// get unique rows by column 1
console.log(getUniqueData(data, [0]));
// get unique rows by column 1 and then by column 2
console.log(getUniqueData(data, [0,1]));
// get unique rows by column 1 and then by column 3
console.log(getUniqueData(data, [0,2]));
// get unique rows by column 1 and then by column 4
console.log(getUniqueData(data, [0,3]));
// get unique rows by column 3
console.log(getUniqueData(data, [2]));
// get unique rows by column 4
console.log(getUniqueData(data, [3]));
// get unique rows by column 2, then by column 3, then by column 4
console.log(getUniqueData(data, [1,2,3]));
// etc

Finding the lonely integer - JavaScript [duplicate]

This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 8 months ago.
Consider the array [1,2,2]
The array contains two unique values: 1, 2
The array contains duplicate values: 2
The lonely integer is 1
How can the lonely integer be returned?
For an array where you only care about grabbing the first integer which is lonely, you can check if the indexOf and lastIndexOf are the same. If they are, then it's lonely.
const array = [2, 2, 1, 3, 4, 3, 4];
const findLonely = (arr) => {
for (const num of arr) {
if (arr.indexOf(num) === arr.lastIndexOf(num)) return num;
}
return 'No lonely integers.';
};
console.log(findLonely(array));
If you have an array that has multiple lonely values, you can use this method to find all of the lonely values:
const array = [2, 2, 1, 3, 4, 3, 4, 6, 8, 8, 9];
const findAllLonely = (arr) => {
const map = {};
arr.forEach((num) => {
// Keep track of the number of time each number appears in the array
if (!map[num]) return (map[num] = 1);
map[num]++;
});
// Filter through and only keep the values that have 1 instance
return Object.keys(map).filter((key) => {
return map[key] === 1;
});
};
console.log(findAllLonely(array)); // expect [1, 6, 9]
const array = [0,1,2,2,1,5,4,3,4,3,2];
let lonely = array.filter((item,index)=> array.indexOf(item) === array.lastIndexOf(item));
console.log(lonely);
Working Demo :
// Array with duplicates
const arrWithDuplicates = [1, 2, 2];
var result = arrWithDuplicates.sort().filter((x,i,arr) => x !== arr[i+1] && x !== arr[i-1]);
console.log(result); // [1]
For each element your can use .filter() to help count the how many times the element is repeated. Then use .filter() again to return only those elements that appear once.
const nums = [1,2,2,3,4,4,4,5,5,6,7,7,7,8,8];
const singles = nums.filter(
//count how many times each element appears
num => nums.filter(n => n === num)
//return only those with freq. of 1
.length === 1
);
console.log( singles );
//OUTPUT: [ 1, 3, 6 ]
Use a 'for' loop with the filter function to loop through the array and only return the value that appears once
const arr = [0, 1, 2, 2, 1];
let unique;
for(var i = 0; i < arr.length; i++) {
if(a.filter(x => x == arr[i]).length == 1) {
unique = arr[i]
}
}
return unique;
the code below solves the challenge with O(n) complexity
function lonelyinteger(a) {
let result;
a.every((e)=>{
if(a.filter(x=>x==e).length==1) {
result = e;
return false;
}return true;
})
return result;
}
O(n) complexity
function lonelyinteger(a) {
for (let i = 0; i < a.length; i++) {
const count = a.filter((v) => v === a[i]).length;
if (count === 1) {
console.log(a[i]);
return a[i];
}
}
}
If there is multiple unique number in an array = [1,2,3,4,5,3,2,1] here 4 and 5 both are unique ,there is two lonely integer so the output should be like this result = [4,5]. In case of single unique integer we can return the result as result = [3] or result = 3. The below code snippet will solve both the scenario.
const array = [1,2,3,4,5,3,2,1]
let result = []
array.every(e => {
if(array.filter(x => x == e).length == 1) {
result.push(e)
}
return true
})
console.log(result)
Explanation: step by step
Your desire array from where you need to get the lonely integer.
We defined result as an array.
You can use simple for loop or array forEach (learn about forEach).
We are using array filter method (learn about filter) to get our work done. Here array.filter(x => x == e) this will result when the value of e is 1 (first element of the array) then the output will be [1,1].
So for 1 the .length == 1 will return false. This process will continue to get false and the if condition will not get executed until a the 'e' became 4 (4th element of the main array).
When 'e' became 4 then the result of array.filter(x => x == 4) will be [4] so the condition array.filter(x => x == e).length == 1 will be true and the if condition will execute. And inside that we are pushing the value 4 to the result array. You can add a next line return false to stop the execution and you will get only one single lonely integer.
return true is required here only if you're using the every method (learn about array every method)
Play with the code to get better understanding or comment if you've some question about this solution. Please give a up-vote if this answer is helpful.

Find indices of all duplicate records in js

Suppose I have an array as below:
Arr1 = [12,30,30,60,11,12,30]
I need to find index of elements which are repeated in array e.g.
ans: 0,1,2,5,6
I've tried this code but it is considering just single element to check duplicates.
First get all the duplicates using filter() and then using reduce() get he indexes of only those elements of array which are in dups
const arr = [12,30,30,60,11,12,30];
const dups = arr.filter(x => arr.indexOf(x) !== arr.lastIndexOf(x));
const res = arr.reduce((ac, a, i) => {
if(dups.includes(a)){
ac.push(i)
}
return ac;
}, []);
console.log(res)
The time complexity of above algorithm is O(n^2). If you want O(n) you can use below way
const arr = [12,30,30,60,11,12,30];
const dups = arr.reduce((ac, a) => (ac[a] = (ac[a] || 0) + 1, ac), {})
const res = arr.reduce((ac, a, i) => {
if(dups[a] !== 1){
ac.push(i)
}
return ac;
}, []);
console.log(res)
You could use simple indexOf and the loop to get the duplicate indexes.
let arr = [12,30,30,60,11,12,30]
let duplicate = new Set();
for(let i = 0; i < arr.length; i++){
let index = arr.indexOf(arr[i], i + 1);
if(index != -1) {
duplicate.add(i);
duplicate.add(index);
}
}
console.log(Array.from(duplicate).sort().toString());
A slightly different approach with an object as closure for seen items which holds an array of index and the first array, in which later comes the index and a necessary flattening of the values.
This answer is based on the question how is it possible to insert a value into an already mapped value.
This is only possible by using an object reference which is saved at the moment where a value appears and which is not seen before.
Example of unfinished result
[
[0],
[1],
2,
[],
[],
5,
6
]
The final Array#flat removes the covering array and shows only the index, or nothing, if the array remains empty.
[0, 1, 2, 5, 6]
var array = [12, 30, 30, 60, 11, 12, 30],
indices = array
.map((o => (v, i) => {
if (o[v]) { // if is duplicate
o[v][1][0] = o[v][0]; // take the first index as well
return i; // return index
}
o[v] = [i, []]; // save index
return o[v][1]; // return empty array
})({}))
.flat() // remove [] and move values out of array
console.log(indices);
You could use Array#reduce method
loop the array with reduce.At the time find the index of argument
And check the arguments exist more than one in the array using Array#filter
Finaly push the index value to new accumulator array.If the index value already exist in accumalator.Then pass the currentIndex curInd of the array to accumulator
const arr = [12, 30, 30, 60, 11, 12, 30];
let res = arr.reduce((acc, b, curInd) => {
let ind = arr.indexOf(b);
if (arr.filter(k => k == b).length > 1) {
if (acc.indexOf(ind) > -1) {
acc.push(curInd)
} else {
acc.push(ind);
}
}
return acc;
}, []);
console.log(res)
Below code will be easiest way to find indexes of duplicate elements
var dupIndex = [];
$.each(Arr1, function(index, value){
if(Arr1.filter(a => a == value).length > 1){ dupIndex.push(index); }
});
This should work for you

Check if a JavaScript 2D array is in ascending order?

Suppose I have an array as such
var arr = [ [1,2,3],[4,5,1]]
How do I check if the columns are in ascending order?
For first column 1<4 returns true but the last column returns false as 3 is not less than 1.
The result should return an array of the columns that returns false
I would do it by first transposing the matrix (simply because its easier to deal with in js) and then map over each column (converting them from a set of numbers into a bool using Array#every).
const arr = [
[1,2,3],
[4,5,1]
];
const transpose = (arr) => Array(arr[0].length)
.fill(0)
.map((_, colIndex) => {
return Array(arr.length)
.fill(0)
.map((_, rowIndex) => {
return arr[rowIndex][colIndex];
});
});
const arr2 = transpose(arr);
const arr3 = arr2.map(col => {
let previousValue = -Infinity;
return col.every(v => {
const tmp = previousValue < v;
previousValue = v;
return tmp;
});
});
console.log(arr);
console.log(arr2);
console.log(arr3);
One possible solution is to use Array.map() over the first inner array, and then check if you found some element on a particular column that is not in order using Array.some():
var arr = [
[1, 2, 3],
[4, 5, 1],
[6, 7, 2]
];
let res = arr[0].map((n, cIdx) =>
{
return !arr.some((inner, rIdx) => rIdx > 0 && inner[cIdx] < arr[rIdx - 1][cIdx]);
});
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
To find the "columns" with the two values in descending order, you can use parallel arrays. Here is a succinct version of the code for that. (The second snippet is more verbose and provides further explanation.)
var arr = [ [1,2,3], [4,5,1] ], result = [];
arr[0].forEach((n, i) => { // n is the number, i is the index
if(arr[0][i] > arr[1][i]){ result.push(i); } // if descending, remember this index
});
console.log(result); // Logs `[2]` (an array with the index of the third column)
If you want to change which "column" the values are in so that they will be in ascending order, you could do it like this. When you find a "misplaced" value, store it in a temporary variable to make room. Then you can assign the two values to their "correct" locations.
const bigArr = [ [1,2,3], [4,5,1] ],
a1 = bigArr[0],
a2 = bigArr[1],
resultArr = [],
len = Math.min(a1.length, a2.length); // Uses min in case they have different lengths
for(let i = 0; i < len; i++){
if(a1[i] > a2[i]){ // Checks each position, and exchanges values if necessary
exchangeValuesInParallelArrays(a1, a2, i);
resultArr.push(i); // Adds this index to the results array
}
}
console.log(bigArr); // Logs `[ [1,2,1], [4,5,3] ]`
console.log(resultArr) // Logs `[2]`
function exchangeValuesInParallelArrays(arr1, arr2, index){
let tempStorage = arr1[index];
arr1[index] = arr2[index];
arr2[index] = tempStorage;
}

find intersection elements in arrays in an array

I need to construct a function intersection that compares input arrays and returns a new array with elements found in all of the inputs.
The following solution works if in each array the numbers only repeat once, otherwise it breaks. Also, I don't know how to simplify and not use messy for loops:
function intersection(arrayOfArrays) {
let joinedArray = [];
let reducedArray = [];
for (let iOuter in arrayOfArrays) {
for (let iInner in arrayOfArrays[iOuter]) {
joinedArray.push(arrayOfArrays[iOuter][iInner]);
}
return joinedArray;
}
for (let i in joinedArray.sort()) {
if (joinedArray[i] === joinedArray[ i - (arrayOfArrays.length - 1)]) {
reducedArray.push(joinedArray[i]);
}
}
return reducedArray;
}
Try thhis:-
function a1(ar,ar1){
x = new Set(ar)
y = new Set(ar1)
var result = []
for (let i of x){
if (y.has(i)){
result.push(i)
}
}
if (result){return result}
else{ return 0}
}
var a= [3,4,5,6]
var b = [8,5,6,1]
console.log(a1(a,b)) //output=> [5,6]
Hopefully this snippet will be useful
var a = [2, 3, 9];
var b = [2, 8, 9, 4, 1];
var c = [3, 4, 5, 1, 2, 1, 9];
var d = [1, 2]
function intersect() {
// create an empty array to store any input array,All the comparasion
// will be done against this one
var initialArray = [];
// Convert all the arguments object to array
// there can be n number of supplied input array
// sorting the array by it's length. the shortest array
//will have at least all the elements
var x = Array.prototype.slice.call(arguments).sort(function(a, b) {
return a.length - b.length
});
initialArray = x[0];
// loop over remaining array
for (var i = 1; i < x.length; i++) {
var tempArray = x[i];
// now check if every element of the initial array is present
// in rest of the arrays
initialArray.forEach(function(item, index) {
// if there is some element which is present in intial arrat but not in current array
// remove that eleemnt.
//because intersection requires element to present in all arrays
if (x[i].indexOf(item) === -1) {
initialArray.splice(index, 1)
}
})
}
return initialArray;
}
console.log(intersect(a, b, c, d))
There is a nice way of doing it using reduce to intersect through your array of arrays and then filter to make remaining values unique.
function intersection(arrayOfArrays) {
return arrayOfArrays
.reduce((acc,array,index) => { // Intersect arrays
if (index === 0)
return array;
return array.filter((value) => acc.includes(value));
}, [])
.filter((value, index, self) => self.indexOf(value) === index) // Make values unique
;
}
You can iterate through each array and count the frequency of occurrence of the number in an object where the key is the number in the array and its property being the array of occurrence in an array. Using the generated object find out the lowest frequency of each number and check if its value is more than zero and add that number to the result.
function intersection(arrayOfArrays) {
const frequency = arrayOfArrays.reduce((r, a, i) => {
a.forEach(v => {
if(!(v in r))
r[v] = Array.from({length:arrayOfArrays.length}).fill(0);
r[v][i] = r[v][i] + 1;
});
return r;
}, {});
return Object.keys(frequency).reduce((r,k) => {
const minCount = Math.min(...frequency[k]);
if(minCount) {
r = r.concat(Array.from({length: minCount}).fill(+k));
}
return r;
}, []);
}
console.log(intersection([[2,3, 45, 45, 5],[4,5,45, 45, 45, 6,7], [3, 7, 5,45, 45, 45, 45,7]]))

Categories

Resources