Filtering Arrays in Javascript [duplicate] - javascript

This question already has answers here:
How to get the difference between two arrays in JavaScript?
(84 answers)
Closed 6 years ago.
Say I have the following two arrays:
var arrOne = [1, 4, 7];
var arrTwo = [1, 2, 3, 4, 5];
var arrThree = [];
I'd like to itterate over arrTwo and if it contains an element that is also in arrOne, remove it from arrTwo, and insert it in arrThree. So looking at the above arrays the state of the arrays afterwards should look like this:
var arrOne = [1, 4, 7];
var arrTwo = [2, 3, 5];
var arrThree = [1, 4];
Could anyone point me in the right direction and the best way to go about this? If code is provided, a step-by-step explanation would really be appreciated so that I can understand what's going on.

A simple for loop, matching with indexOf and splicing matches.
var arrOne = [1, 4, 7];
var arrTwo = [1, 2, 3, 4, 5];
var arrThree = [];
for (var i = 0; i < arrTwo.length; i++) {
if (arrOne.indexOf(arrTwo[i]) >= 0) {
arrThree.push(arrTwo[i]);
arrTwo.splice(i, 1);
i--;
}
}
console.log(arrOne, arrTwo, arrThree)
Array.IndexOf
Array.splice

Look into the Underscore library. All the elements in arrOne that are also in arrTwo is called _.intersection().

Use simple while loop with Array#splice and Array#unshift methods.
var arrOne = [1, 4, 7];
var arrTwo = [1, 2, 3, 4, 5];
var arrThree = [];
// get length of array
var l = arrTwo.length;
// iterate over array from the end
while (l--) {
// check value present in arrOne
if (arrOne.indexOf(arrTwo[l]) > -1)
// if present then remove and insert it
// at the beginning of arrThree
arrThree.unshift(arrTwo.splice(l, 1)[0])
}
console.log(arrTwo, arrThree);

Hi You can use filter function to filter array.
try with below code.
var arrOne = [1, 4, 7];
var arrTwo = [2, 3, 5, 1];
var arrThree = [];
function checkValue(a) {
return !arrOne.indexOf(a);
}
function checkValue2(a) {
return arrThree.indexOf(a);
}
function myFunction() {
arrThree = arrTwo.filter(checkValue);
document.getElementById("demo").innerHTML = arrThree ;
arrTwo = arrTwo.filter(checkValue2);
document.getElementById("demo1").innerHTML = arrTwo;
}

var arrOne = [1, 4, 7];
var arrTwo = [1, 2, 3, 4, 5];
var arrThree = diff(arrOne,arrTwo);//passes the two arrays
console.log(arrThree);
function diff(one, two){
one.forEach(function(e1){ //iterate through the first array
two.forEach(function(e2){//iterate through second
if(e1 == e2) //checking if elements are equal
two.pop(e2);//removing from second array
});
});
return two; //returning new array
}
You can use underscore js for easy array operations, the difference operation will be _.difference([1, 2, 3, 4, 5], [5, 2, 10]);.

var array1 = [1, 2, 3, 4, 5, 6],
var array2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var common = $.grep(array1, function(element) {
return $.inArray(element, array2) !== -1;
});
console.log(common); // returns [1, 2, 3, 4, 5, 6];
array2 = array2.filter(function(obj) {
return array1.indexOf(obj) == -1;
});
// returns [7,8,9];

Since the arrays are sorted you could read them in parallel : O(n) instead of O(n2). Don't use a library for such a simple problem, this is overkill :-)
var i = 0, j = 0;
var a = [1, 4, 7];
var b = [1, 2, 3, 4, 5];
var c = [];
while (i < a.length && j < b.length) {
if (a[i] < b[j]) i++;
else if (a[i] > b[j]) j++;
else c.push(b.splice(j, 1)[0]);
}
console.log("a " + toString(a));
console.log("b " + toString(b));
console.log("c " + toString(c));
function toString (v) {
return "[ " + v.join(" ") + " ]";
}
Trace :
#0 init
a = [ 1 4 7 ]
i
b = [ 1 2 3 4 5 ]
j
c = []
#1 a[i] = b[j] => move b[j] to c
a = [ 1 4 7 ]
i
b = [ 2 3 4 5 ]
j
c = [ 1 ]
#2 a[i] < b[j] => increment i
a = [ 1 4 7 ]
i
b = [ 2 3 4 5 ]
j
c = [ 1 ]
#3 a[i] > b[j] => increment j
a = [ 1 4 7 ]
i
b = [ 2 3 4 5 ]
j
c = [ 1 ]
#4 a[i] > b[j] => increment j
a = [ 1 4 7 ]
i
b = [ 2 3 4 5 ]
j
c = [ 1 ]
#5 a[i] = b[j] => move b[j] to c
a = [ 1 4 7 ]
i
b = [ 2 3 5 ]
j
c = [ 1 4 ]
#6 a[i] < b[j] => increment i
a = [ 1 4 7 ]
i
b = [ 2 3 5 ]
j
c = [ 1 4 ]
#7 a[i] > b[j] => increment j
a = [ 1 4 7 ]
i
b = [ 2 3 5 ]
j
c = [ 1 4 ]
#8 j = length of b => done

Related

A function that returns a new array, the values ​of this array must not be repeated more than n times

A task:
Write a function that takes an array and a number n. Then output an array in which there are no elements that are repeated more than n times.
Example:
Input:
n = 3;
arr = [1, 2, 4, 4, 4, 2, 2, 2, 2]
Output:
result = [1, 2, 4, 4, 4, 2, 2]
Tried to do something like that, but it's not working correctly.
let arr = [1, 2, 4, 4, 4, 2, 2, 2, 2];
let new_set = [...new Set(arr)];
let result = [];
console.log(new_set); // [1, 2, 4]
first:
for (let i = 0; i < arr.length; i++) {
if (arr[i] === arr[i - 1]) {
continue first;
}
else {
let count = 0;
for (let j = i; j < arr.length; j++) {
if ((arr[i] === arr[j]) && (count < 3)) {
result.push(arr[j]);
}
}
}
}
You need a persistent outer variable that keeps track of how many times an item has been iterated over so far. Once past the limit, don't push the item being iterated over to the result.
const arr = [1, 2, 4, 4, 4, 2, 2, 2, 2]
let n = 3;
const counts = {};
const result = [];
for (const item of arr) {
counts[item] = (counts[item] || 0) + 1;
if (counts[item] <= n) {
result.push(item);
}
}
console.log(result);
Another option, if you want to use Array.reduce.
It's not as optimised as #CertainPerformance as it uses a filter inside a loop. But for small arrays like this unlikely to make much difference.
const arr = [1, 2, 4, 4, 4, 2, 2, 2, 2]
let n = 3;
const result = arr.reduce((a,v)=>(
a.filter(f=>f===v).length < n ?a.push(v):a,a),[]);
console.log(result);
Code golf version using reduce and without array.filter:
const f=(n,a)=>a.reduce((({c={},r=[]},i)=>
(c[i]??=0,++c[i]>n?0:r.push(i),{c,r})),{}).r;
console.log(f(3, [1, 2, 4, 4, 4, 2, 2, 2, 2]).join());

Find single occurrence of an element in an array

I'm trying to find single occurrence of an element in an array. But it only shows for 1 element. Where is the logic going wrong?
function findSingle(array){
var arrayCopy = array.slice(0);
var x;
var y = [];
for (var i = 0; i < array.length; i++) {
x = arrayCopy.splice(i, 1)
if(arrayCopy.includes(array[i]) === false){
console.log(array[i] + " is single")
}
arrayCopy = arrayCopy.concat(x)
}
}
findSingle([1, 3, 3, 6])
You can use a double Array.filter() to remove numbers that appear more than once:
function findSingle(arr) {
return arr.filter(i => arr.filter(j => i === j).length === 1)
}
const result = findSingle([1, 3, 3, 6, 8, 4, 6])
console.log(result) // [1, 8, 4]
Bear in mind that this will only work for Numbers and other primitives because of the way that Javascript evaluates equality and sameness.
I added some console.logs to see what was happening and the problem is that you're changing the order of elements in arrayCopy. And so 6 is never checked.
Checking for [ 1 ]
arrayCopy is [ 3, 3, 6 ]
1 is single
After adding to arrayCopy [ 3, 3, 6, 1 ]
Checking for [ 3 ]
arrayCopy is [ 3, 6, 1 ]
After adding to arrayCopy [ 3, 6, 1, 3 ]
Checking for [ 1 ]
arrayCopy is [ 3, 6, 3 ]
After adding to arrayCopy [ 3, 6, 3, 1 ]
Checking for [ 1 ]
arrayCopy is [ 3, 6, 3 ]
After adding to arrayCopy [ 3, 6, 3, 1 ]
You can probably use a frequency map to find the number of occurrences in each element and then filter keys that occur only once.
function findSingle(array){
var freqs = {};
array.forEach(n => {
if (!(n in freqs)) freqs[n] = 1;
else freqs[n] += 1;
});
return Object.keys(freqs).filter(k => freqs[k] === 1);
}
This could be done by creating an object that could map element and its occurrence.
So here is a code
function findSingle(arr){
var counts = {};
var singles = [];
for (var i = 0; i < arr.length; i++) {
var num = arr[i];
counts[num] = counts[num] ? counts[num] + 1 : 1;
}
for(var num in counts) {
if(counts[num] == 1)
singles.push(num);
}
return singles.map(x => Number(x));
}
The output of findSingle([1, 3, 3, 6]) will be
[1, 6]
Note This can work with string too but it may be numbers. For example, ["1", "3", "3", "6"]

Convert a 1D array to 2D array [duplicate]

This question already has answers here:
Convert simple array into two-dimensional array (matrix)
(19 answers)
Closed 8 years ago.
I am working on a program where I have to read the values from a textfile into an 1D array.I have been succesfull in getting the numbers in that 1D array.
m1=[1,2,3,4,5,6,7,8,9]
but I want the array to be
m1=[[1,2,3],[4,5,6],[7,8,9]]
You can use this code :
const arr = [1,2,3,4,5,6,7,8,9];
const newArr = [];
while(arr.length) newArr.push(arr.splice(0,3));
console.log(newArr);
http://jsfiddle.net/JbL3p/
Array.prototype.reshape = function(rows, cols) {
var copy = this.slice(0); // Copy all elements.
this.length = 0; // Clear out existing array.
for (var r = 0; r < rows; r++) {
var row = [];
for (var c = 0; c < cols; c++) {
var i = r * cols + c;
if (i < copy.length) {
row.push(copy[i]);
}
}
this.push(row);
}
};
m1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
m1.reshape(3, 3); // Reshape array in-place.
console.log(m1);
.as-console-wrapper { top:0; max-height:100% !important; }
Output:
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
JSFiddle DEMO
I suppose you could do something like this... Just iterate over the array in chunks.
m1=[1,2,3,4,5,6,7,8,9];
// array = input array
// part = size of the chunk
function splitArray(array, part) {
var tmp = [];
for(var i = 0; i < array.length; i += part) {
tmp.push(array.slice(i, i + part));
}
return tmp;
}
console.log(splitArray(m1, 3)); // [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
Obviously there is no error checking, but you can easily add that.
DEMO
There are so many ways to do the same thing:
var m = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var n = [];
var i = 0;
for (l = m.length + 1; (i + 3) < l; i += 3) {
n.push(m.slice(i, i + 3));
}
// n will be the new array with the subarrays
The above is just one.

Javascript getting the oldest element in the array

Lets say that I am to remove the oldest element of an array, because I wanted to replace it with a new value. (first-in-first-out).
For example, I have this array of values
var arr = [1,2,3,4,5,6,7]
And I wanted to only get the first three, values, and then on the 4th, replace the element who came first
[1,2,3], [4,2,3], [4,5,3] and so on..
I came up with a solution
var arr = [1,1,2,3,4,5,6,7];
var newArr = [];
for(i=0; i<arr.length; i++){
if(newArr.length == 3 && newArr.indexOf(arr[i]) < 0) {
newArr[i%3] = arr[i];
} else if(newArr.indexOf(arr[i]) < 0) {
newArr.push(arr[i])
}
console.log(newArr)
}
Which will render:
1
1
1,2
1,2,3
1,4,3
1,4,5
6,4,5
6,7,5
Instead of
1
1,2
1,2,3
4,2,3
4,5,3
4,5,6
7,5,6
What am I missing out.
var arr = [1, 1, 2, 3, 4, 5, 6, 7];
var newArr = [], currentIndex = 0;
for (i = 0; i < arr.length; i++) {
if (newArr.length === 3 && newArr.indexOf(arr[i]) < 0) {
newArr[currentIndex % 3] = arr[i];
currentIndex += 1;
} else if (newArr.indexOf(arr[i]) < 0) {
newArr.push(arr[i]);
}
console.log(newArr)
}
Output
[ 1 ]
[ 1 ]
[ 1, 2 ]
[ 1, 2, 3 ]
[ 4, 2, 3 ]
[ 4, 5, 3 ]
[ 4, 5, 6 ]
[ 7, 5, 6 ]
You just need to track the current index where you need to place the number using a separate variable.

javaScript to return a new array of paired values from an array of single values [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Split array into chunks
I am trying to convert an array of values into a new array of paired values.
For example i need to convert:
var arr = [1,2,3,4,5,6,7,8];
into:
arr = [[1,2], [3,4], [5,6], [7,8]];
I tried using jQuery's .map() method like so but this did not work for me:
arr= $.map(arr, function(n, i){
return [n + ',' + n[ i + 1 ]];
});
If you insist on using map, you could do it like this:
arr= $.map(arr, function(n, i){
if (i%2 === 0) return [[n, arr[ i + 1 ]]];
});
If you don't want to use a hammer on a thumbtack:
var arr = [1,2,3,4,5,6,7,8];
var newarr = new Array();
for (var i=0; i<arr.length; i=i+2) {
newarr.push(arr.slice(i,i+2));
}
don't use jquery for every problem:
var arr = [1, 2, 3, 4, 5, 6, 7, 8];
var narr = [];
for (i = 0; i < arr.length; i = i + 2) {
narr[i / 2] = [arr[i], arr[i + 1]];
}
but this only works if you have an even count of arr
Another example...
var arr = [1 , 2, 3, 4, 5, 6, 7, 8]
var final = []
while(arr.length) {
final.push(arr.splice(0, 2))
}
You don't want map, you want reduce.
Here is something that should work:
var endArr = [],
arr = [ 1, 2, 3, 4, 5, 6, 7, 8 ],
i = 0;
arr.reduce( function( prev, curr, index ) {
if ( index % 2 === 0 ) {
endArr[ i ] = [ prev, curr ];
}
i++;
} );
And just something else I thought about:
var endArr = [],
arr = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
while ( arr.length ) {
endArr.push( arr.splice( 0, 2 ) );
}
Edit: Arf, it's the same solution as Chris Gutierrez.

Categories