How to replace array elements in place - javascript

I want to attach a new method to the Array.prototype:
Array.prototype.uniq = function(){
return this.filter((val, index) => {
return this.indexOf(val) === index;
});
};
var a = [1, 1, 2, 3];
console.log(a.uniq()); // output: [1,2,3]
console.log(a); // output: [1,1,2,3]
The method removes duplicates from an array. The problem I have is that whenever uniq is called, a new array is returned. I want to do something like this:
Array.prototype.uniq = function(){
this = this.filter((val, index) => { // "ReferenceError: Invalid left-hand side in assignment
return this.indexOf(val) === index;
});
};
so that:
var a = [1, 1, 2, 3];
a.uniq();
console.log(a); // output: [1,2,3]
What should I do?

You can iterate over the array using for loop and use splice if the index are not same.
Array.prototype.uniq = function () {
// Reverse iterate
for (var i = this.length - 1; i >= 0; i--) {
// If duplicate
if (this.indexOf(this[i]) !== i) {
// Remove from array
this.splice(i, 1);
}
}
// Return updated array
return this;
};
var a = [1, 1, 2, 3];
a.uniq();
console.log(a); // output: [1,2,3]

Related

Difference of array, result is 1 or undefined

Array a = [1,2,3,4,5,5]
Array b = [1,2,3,5]
c = a - b
which should return c = [4] (5 is repeated twice but I dont want it in the output)
Now here is my code:
function arrayDiff(a, b) {
var array = [];
var diff = [];
for (var i = 0; i<a.length; i++) {
array[a[i]] = true;
}
for (var i = 0; i<b.length; i++) {
if (array[b[i]]) {
delete array[b[i]];
}
else {
array[b[i]] = true;
}
for (var k in array) {
return diff.push(k);
}
}
}
Test.describe("Sample tests", function() {
Test.it("Should pass Sample tests", function() {
Test.assertDeepEquals(arrayDiff([], [4,5]), [], "a was [], b was [4,5]");
Test.assertDeepEquals(arrayDiff([3,4], [3]), [4], "a was [3,4], b was [3]");
Test.assertDeepEquals(arrayDiff([1,8,2], []), [1,8,2], "a was [1,8,2], b was []");
});
});
but it returns weird stuff. Can you please explain why it returns 1 and how do I fix it? This is the console.log output:
a was [], b was [4,5] - Expected: [], instead got: 1
a was [3,4], b was [3] - Expected: [4], instead got: 1
a was [1,8,2], b was [] - Expected: [1, 8, 2], instead got: undefined
Unhandled rejection TestError: a was [], b was [4,5] - Expected: [], instead got: 1
Can you please help me fix it?
there are couple of problems in your code
3rd for loop that is nested inside the 2nd for loop should not be nested inside the 2nd loop.
.push() method adds a new item in the array and returns the length of the array after adding the new item. Instead of returning the return value of push function, you need to return diff array.
Here's the fixed code
const a = [1,2,3,4,5,5];
const b = [1,2,3,5];
function arrayDiff(a, b) {
var array = [];
var diff = [];
for (var i = 0; i<a.length; i++) {
array[a[i]] = true;
}
for (var i = 0; i<b.length; i++) {
if (array[b[i]]) {
delete array[b[i]];
}
else {
array[b[i]] = true;
}
}
for (var k in array) {
diff.push(Number(k));
}
return diff;
}
console.log(arrayDiff(a, b));
Edit
As per your comments, if a = [] and b = [1, 2] then output should be [] and for a = [1, 8, 2] and b = [], output should be [1, 8 ,2].
This isn't possible with your code as you are finding the difference based on array indexes and boolean values.
You can get the desired output by filtering the array a and checking if the current element in array a exists in array b or not.
let a = [1, 8 ,2];
let b = [];
function arrayDiff(a, b) {
return a.filter(n => !b.includes(n));
}
console.log(arrayDiff(a, b));
Your code looks good. It may need some modification to make it simple.
function arrayDiff(a, b) {
return a.filter((aItem) => b.indexOf(aItem) === -1);
}
You could take a Set and filter the array.
function arrayDiff(a, b) {
const setB = new Set(b);
return a.filter(v => !setB.has(v));
}
console.log(arrayDiff([1, 2, 3, 4, 5, 5], [1, 2, 3, 5]));

Have one array reference two or more

So I want to know if it's possible to create a scenario like this in javascript:
Lets say I have two arrays:
a = [1, 2, 3]
b = [4, 5, 6]
And then I would like to create an array c that references the two arrays:
c = [1, 2, 3, 4, 5, 6]
However when I change an element in one of the two arrays I would also like to have it automatically affect array c:
a[1] = 1
c = [1, 1, 3, 4, 5, 6]
Is there a way to make this possible in javascript?
The traditional pass-by-reference approach doesn't exist in JavaScript, so you'll have to use a workaround. The simplest way would be to return c dynamically as a combination of a and b using a function. Another would be using an object and getter/setters to manipulate what you get when accessing c.
Example:
var $ = (function () {
/* Hidden arrays */
var a = [1, 2, 3];
var b = [4, 5, 6];
/* Visible object. */
return {
get a () {
return a;
},
set a (v) {
a = v;
},
get b () {
return b;
},
set b (v) {
b = v;
},
get c () {
return a.concat(b);
},
};
})();
/* Example */
console.log(JSON.stringify($.a), JSON.stringify($.b), JSON.stringify($.c));
$.a = [0, 1, 2];
console.log(JSON.stringify($.a), JSON.stringify($.b), JSON.stringify($.c));
$.b[1] = 7;
console.log(JSON.stringify($.a), JSON.stringify($.b), JSON.stringify($.c));
You will need a Proxy.
const a = [1,2,3];
const b = [4,5,6];
const c = new Proxy([a,b], {
_localIndex: function(arrays, index) {
index = +index;
if( isNaN(index)) throw new TypeError("Expected numeric index");
if( Math.floor(index) !== index) throw new RangeError("Index must be an integer");
if( index < 0) throw new RangeError("Index must be positive");
for( let i=0; i<arrays.length; i++) {
if( arrays[i].length > index) return [i,index];
index -= arrays[i].length;
}
throw new RangeError("Index out of bounds");
},
get: function(arrays, index) {
if( index === "length") {
return arrays.reduce((a,c)=>a+c.length,0);
}
if( index === "source") {
return arrays;
}
const [arr, idx] = this._localIndex(arrays, index);
return arrays[arr][idx];
},
set: function(arrays, index, value) {
const [arr, idx] = this._localIndex(arrays, index);
arrays[arr][idx] = value;
}
});
console.log("Get c[4]: "+c[4]);
c[2] = 9;
console.log("Updated c[2], a is now: "+JSON.stringify(a));
console.log("Get c's source array: "+JSON.stringify(c.source));
a.push('x');
console.log("Pushed value to a, c is now: "+JSON.stringify(c.source));
MDN docs

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]]))

Return numbers which appear only once (JavaScript)

Say I have the array [1,2,3,5,2,1,4]. How do I get make JS return [3,4,5]?
I've looked at other questions here but they're all about delete the copies of a number which appears more than once, not both the original and the copies.
Thanks!
Use Array#filter method twice.
var data = [1, 2, 3, 5, 2, 1, 4];
// iterate over elements and filter
var res = data.filter(function(v) {
// get the count of the current element in array
// and filter based on the count
return data.filter(function(v1) {
// compare with current element
return v1 == v;
// check length
}).length == 1;
});
console.log(res);
Or another way using Array#indexOf and Array#lastIndexOf methods.
var data = [1, 2, 3, 5, 2, 1, 4];
// iterate over the array element and filter out
var res = data.filter(function(v) {
// filter out only elements where both last
// index and first index are the same.
return data.indexOf(v) == data.lastIndexOf(v);
});
console.log(res);
You can also use .slice().sort()
var x = [1,2,3,5,2,1,4];
var y = x.slice().sort(); // the value of Y is sorted value X
var newArr = []; // define new Array
for(var i = 0; i<y.length; i++){ // Loop through array y
if(y[i] != y[i+1]){ //check if value is single
newArr.push(y[i]); // then push it to new Array
}else{
i++; // else skip to next value which is same as y[i]
}
}
console.log(newArr);
If you check newArr it has value of:
[3, 4, 5]
var arr = [1,2,3,5,2,1,4]
var sorted_arr = arr.slice().sort(); // You can define the comparing function here.
var nonduplicates = [];
var duplicates=[];
for (var i = 0; i < arr.length; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
duplicates.push(sorted_arr[i]);
}else{
if(!duplicates.includes(sorted_arr[i])){
nonduplicates.push(sorted_arr[i]);
}
}
}
alert("Non duplicate elements >>"+ nonduplicates);
alert("Duplicate elements >>"+duplicates);
I think there could exists option with Map.
function unique(array) {
// code goes here
const myMap = new Map();
for (const el of array) {
// save elements of array that came only once in the same order
!myMap.has(el) ? myMap.set(el, 1) : myMap.delete(el);
}
return [...myMap.keys()];
}
const array = [1,2,3,5,2,1,4];
//[11, 23, 321, 300, 50, 23, 100,89,300];
console.log(unique(array));

Is there any elegant function to find an array in array? Javascript

I want to check if an array contains an array of values rather then a value, for example
var arr = [1, 2, 3];
arr.contains([1, 2]); // returns true
// and
arr.contains([1, 5]); // must be false
There is a method called contains in underscore _.contains but it works like .indexof() in javascript instead it returns true and false and only find a value and not an array
Also there is a method Array.prototype.includes() in javascript that also take single input rather of an array
actually I want to check if second array has all the keys present in
first array I want to check with AND
for example [1,2,3,4].contains([1,4]) must return true where as [1,2,3,4].contains([1,9]) must return false, hope this makes sense,
I'm for now using underscores intersection and second array with
intersection result it must be same, its still long procedure....
You could use Array.prototype.includes() within a for loop
var arr = [1,2,3,4];
function contains(arr) {
for (var i = 0, included = true; i < arr.length
; included = included && this.includes(arr[i]), i++);
return included
}
Array.prototype.contains = contains;
console.log(arr.contains([1, 4]), arr.contains([9, 1]), arr.contains([1, 5]))
You can use a combination of every and indexOf
[1, 2].every(function(e) { return [1, 2, 3].indexOf(e) !== -1 });
would evaluate to true and
[1, 5].every(function(e) { return [1, 2, 3].indexOf(e) !== -1 });
would evaluate to false
The syntax would be a lot shorter in ES6 with arrow functions
[1, 2].every(e => [1, 2, 3].indexOf(e) !== -1)
Try this simple example
var arr = [1, 2, 3];
var searchArr = [1,2];
var isSearchArrAvailable = searchArr.filter( function(value){ if ( arr.indexOf( value ) == -1 ) { return true } else { return false; } } ).length == 0;
console.log( "is SearchArr Available " + isSearchArrAvailable );//this will print true
while var searchArr = [1,5] will print false.
You can refactor it into a function
function hasEveryElement(arr, searchArr)
{
return searchArr.filter( function(value){ if ( arr.indexOf( value ) == -1 ) { return true } else { return false; } } ).length == 0;
}
console.log( hasEveryElement([1,2,3], [1,2]) ) ;
console.log( hasEveryElement([1,2,3], [1,4]) ) ;
You can use every:
function contains(arr, arr2) {
return arr2.every(function (el) {
return arr.indexOf(el) > -1;
});
}
var arr = [1, 2, 3];
contains(arr, [1, 2]); // true
contains(arr, [1, 5]); // false
Alternatively, you could add a method to the prototype if you wanted the [].includes-style syntax, but call it something else - I've used hasAll.
if (!('hasAll' in Array.prototype)) {
Array.prototype.hasAll = function(arr) {
return arr.every(function(el) {
return this.indexOf(el) > -1;
}, this);
}
arr.hasAll([1, 2])); // true
arr.hasAll([1, 5])); // false
DEMO
Try this:
var arr = [1,2,3];
var temparr=[1,2];
var st=ArrOfArrSt(arr,temparr);
function ArrOfArrSt(arr,temparr){
var stArr= new Array();
if(temparr.length>0)
for(j in temparr){
if(arr.indexOf(temparr[j])==-1){
stArr.push('0');
}
}
return (stArr.length>0)?0:1; //whole array 0=not belong to / 1=belong to
}

Categories

Resources