Javascript/jQuery: Remove item from multidimensional array by value - javascript

I have a dynamically generated multidimensional array from which I want to remove a specific value.
I have this code, so far:
mainARR = [[1,2,3,4], [5,6,7,8]];
delARR = [1,2,3,4];
function removeByValue(array, value){
return array.filter(function(elem, _index){
return value != elem;
});
}
mainARR = removeByValue(mainARR, delARR);
console.log(JSON.stringify(mainARR));
I don't know the index of the value I want to remove. Instead, I know the actual value. The code does not work when the value is an array. It works perfectly for simple arrays like [1,2,3,4] when I want to remove, let's say, the value 1.
Any help is appreciated.

If you make the elem and value into a string then your code works just fine.
function removeByValue(array, value) {
return array.filter(function(elem, _index) {
return value.toString() != elem.toString();
});
}
Example below
mainARR = [
[1, 2, 3, 4],
[5, 6, 7, 8]
];
delARR = [1, 2, 3, 4];
function removeByValue(array, value) {
return array.filter(function(elem, _index) {
return value.toString() != elem.toString();
});
}
mainARR = removeByValue(mainARR, delARR);
console.log(JSON.stringify(mainARR));

You will have to compare every element inside array.
Example solution:
mainARR = [[1,2,3,4], [5,6,7,8]];
delARR = [1,2,3,4];
function removeByValue(array, value){
return array.filter(function(elem, _index){
// Compares length and every element inside array
return !(elem.length==value.length && elem.every(function(v,i) { return v === value[i]}))
});
}
mainARR = removeByValue(mainARR, delARR);
console.log(JSON.stringify(mainARR));
This should work on sorted and unsorted arrays.

You could filter the values and then delete empty arrays as well.
var mainARR = [[1, 2, 3, 4], [5, 6, 7, 8]],
delARR = [1, 2, 3, 4],
result = mainARR.map(a => a.filter(b => !delARR.includes(b))).filter(a => a.length);
console.log(result);

Related

Delete Duplicate from Two arrays and display one of the arrays in javascript

I want delete duplicate array from two arrays, but just show one of array, how I can do it ?
I want result
[1, 4]
const arr1 = [1, 2, 3, 4];
const arr2 = [2, 3, 5, 6]
function arrayUniq(arr1, arr2) {
enter code here
}
As #Titus said, just filter the array comparing if one of them have repeated values.
const arr1 = [1, 2, 3, 4];
const arr2 = [2, 3, 5, 6];
function arrayUniq(arr1, arr2) {
const arrays = [...arr1,...arr2]
return arrays.filter(a=> !arr2.includes(a))
}
console.log(arrayUniq(arr1,arr2))
// remove duplicates from arr1 and arr2
function arrayUniq(arr1, arr2) {
let result = [];
// Find unique elements in arr1 & push them into result
arr1.forEach((e) => (arr2.find((f) => f === e) ? null : result.push(e)));
// Find unique elements in arr2 & push them into result
arr2.forEach((e) => (arr1.find((f) => f === e) ? null : result.push(e)));
return result;
}
console.log(arrayUniq(arr1, arr2));

Sort an object according to an array with underscore

I am trying to sort an object comparing with an array. So the loop will look for specific values on the array, until it finds one, and put those 3 elements at the beginning and the rest at the end.
I am unsure what is the best way to do this any ideas?
It is something like that:
var arr = [1, 3, 2,4,5,6, 2];
var arrSimilar = [1,2,5]
var testSortBy = _.sortBy(arr, function(arrSimilar){
// [1,2,5,3,4,6,2]
});
console.log(testSortBy); // [1,2,5,3,4,6,2]
You could use sorting with map and take the index of the value of similar array as priority sorting and then take the index of all other values as order.
Important is to delete a used value of the similar array, because it is now in use and has no meaning for further similar values. That means, same values are sorted to their original relative index.
var array = [1, 3, 2, 4, 5, 6, 2],
similar = [1, 2, 5],
result = array
.map(function (a, i) {
var priority = similar.indexOf(a);
delete similar[priority]; // delete value, but keep the index of other items
return { index: i, priority: (priority + 1) || Infinity };
})
.sort(function (a, b) {
return a.priority - b.priority || a.index - b.index;
})
.map(function (o) {
return array[o.index];
});
console.log(result); // [1, 2, 5, 3, 4, 6, 2]
You can do that in the following way
Suppose A[] is the original array and B is the priority Array
The answer would be (B intersection A) concat (A-B)
var arr = [1, 3, 2,4,5,6];
var arrSimilar = [1,2,5];
let bInterA = arrSimilar.filter((e) => arr.indexOf(e) != -1);
let aDiffb = arr.filter((e) => arrSimilar.indexOf(e) == -1);
console.log(bInterA.concat(aDiffb));

Can i sort nested array using nested sort()?

This should be the input array
var a = [2,1,3,4,1,[4,6,2,4],2,4,1];
For the output i have two cases :- (index of internal array is not changing)
a = [1,1,2,3,4,[2,4,4,6],1,2,4]
and
a = [1,1,1,2,2,[2,4,4,6],3,4,4]
This is what i am trying to use :-
a.sort(function(a,b){
if(b instanceof Array){
b.sort();
}
})
Array.sort() is not built to handle partial Arrays, what you would need in your case, but we can work around this problem by pre-processing the data (wrapping it with additional information), then sorting and at the end, extracting the original values:
case 1: sorting the parts between the Arrays
[2,1,3,4,1,[4,6,2,4],2,4,1] -> [1,1,2,3,4,[2,4,4,6],1,2,4]
function sort1(arr){
//I add an artificial "property" of to the values, to "describe" the groups, and to be able to sort by
//each Array is it's own group (so they stay in order), and the values in between share the same group
var group = 0,
isArray = false;
//an intermediate Array holding all the information (in order) to either apply it to the current Array, or to return (map) it as a new Array
var intermediate = arr.map(function(v,i){
//last value was an Array, this is the first value after an Array, start a new group
if(isArray) ++group;
if(isArray = Array.isArray(v)){ //update isArray
v = sort1(v); //recursive sorting
++group; //the last group just ended here
}
//return a composition, that contains all the data I need to sort by
return {
group: group,
value: v
}
}).sort(function(a, b){
//forst sort by group, and (only) if two values share the same group, sort by the original value
return a.group - b.group || a.value - b.value
});
//apply data to current Array
intermediate.forEach(function(obj, i){ arr[i] = obj.value });
return arr;
//return new Array
//return intermediate.map(function(obj){ return obj.value });
}
case 2: treating an Array like it's first value
[2,1,3,4,1,[4,6,2,4],2,4,1] -> [1,1,1,2,2,[2,4,4,6],3,4,4]
function sort2(arr){
//an utility to fetch the first non-array value recursively
function _value(v){
while(Array.isArray(v)) v = v[0];
return v;
}
var intermediate = arr.map(function(v, i){
if(Array.isArray(v)) v = sort2(v);
return {
index: i,
value: v,
sortingValue: _value(v)
}
}).sort(function(a, b){
return a.sortingValue - b.sortingValue || a.index - b.index;
});
//apply data to current Array
intermediate.forEach(function(obj, i){ arr[i] = obj.value });
return arr;
//return new Array
//return intermediate.map(function(obj){ return obj.value });
}
This is the perfect solution, use nested function invoke to sort array.
Firstly , store all the array position and sub array.
Secondly, extract numbers into new array,
Finally insert sorted array into same position as before.
var a = [2,1,3,4,1,[4,6,[4,5,[7,3,2,1,6],1,2],2,4],2,4,1];
function nestedSort(arr){
var items = [];
var numArr = [];
for ( key in arr){
if (arr[key] instanceof Array)
{
items.push({index:key,array:arr[key]});
}else{
numArr.push(arr[key]);
}
}
numArr.sort();
for (key in items){
numArr.splice(items[key].index,0,nestedSort(items[key].array));
}
return numArr;
}
console.log(nestedSort(a));
[
1,
1,
1,
2,
2,
[
2,
4,
[
1,
2,
[
1,
2,
3,
6,
7
],
4,
5
],
4,
6
],
3,
4,
4
]
Hope this can solve your problem. :)
You can loop over array and remove all sub arrays and save their index and then sort the new array and again push sorted sub arrays on specific indexes.
Sample
var arr = [2, 1, 3, 4, 1, [4, 6, 2, 4], 2, 4, 1];
var arr1 = [2, 1, 3, 4, 1, [4, 6, 2, 4], 2, 6, 4, [4, 5, 3], 1, 2, 1, 3]
var a = [2,1,3,4,1,[4,6,[4,5,[7,3,2,1,6],1,2],2,4],2,4,1];
function mySort(arr) {
var _list = [];
arr.forEach(function(item, index) {
if (Array.isArray(item)) {
_list.push({
index: index,
value: arr.splice(index, 1).pop()
});
}
});
arr.sort();
_list.forEach(function(item) {
arr.splice(item.index, 0, mySort(item.value))
})
return arr;
}
console.log(mySort(arr.slice()))
console.log(mySort(arr1.slice()))
console.log(mySort(a.slice()))
Edit 1
Inspired from joey-etamity's answer, have made it generic for nested structure.
No, you don't put the sort call in the comparison function. You would recurse through your arrays, bottom to top, and sort them one after the other. In your case you might not even need recursion if it's only one array in another:
a.forEach(function(element) {
if (Array.isArray(element))
element.sort(function compare(a, b) { return a-b; });
})
(I've chosen a simple numerical compare here).
Then you'd sort the outer array:
a.sort(function compare(a, b) {
if (Array.isArray(a)) a = a[0];
if (Array.isArray(b)) b = b[0];
return a - b;
})
(here compare takes the first element of the array to compare by that against the other numbers).
I suggest to splice the array if there is an element an array. Then sort the array and reassemble the array.
This proposal iterates from the back and keeps the array intact while splicing.
function sort(array) {
var i = array.length,
inside = [];
while (i--) {
if (Array.isArray(array[i])) {
inside.unshift({ pos: i, value: sort(array.splice(i, 1)[0]) });
}
}
array.sort(function (a, b) { return a - b; });
inside.forEach(function (a) {
array.splice(a.pos, 0, a.value);
});
return array;
}
var a = [2, 1, 3, 4, 1, [4, 6, 2, 4], 2, 4, 1];
console.log(sort(a));
I think this would be better to use Array.prototype.sort this way:
// var arr = [2, 1, 3, 4, 1, [4, 6, 2, 4], 2, 4, 1];
var arr = [2, 1, 3, 4, 1, [4, 6, 2, 4], 2, 6, 4, [4, 5, 3], 1, 2, 1, 3];
var chunks = chunkate(arr)
console.log(JSON.stringify(chunks));
chunks.forEach(ch => ch.sort(_sort));
var result = chunks.reduce((p, c) => p.concat(c));
console.log(JSON.stringify(result));
function _sort(a, b) {
var isAa = Array.isArray(a),
isAb = Array.isArray(b);
isAb && b.sort(_sort);
return (isAa || isAb) ? 0 : a - b;
}
function chunkate(arr) {
return arr.reduce((a, c) => {
Array.isArray(c) ? a.push(chunkate(c), []) : a[a.length - 1].push(c)
return a;
}, [[]]);
}
How it works?
If items to compare are are array then they shouldn't be replaced so by sending false sort function recognize that there is no need to replace. Otherwise the simple compare is the answer.
Edit
As discussed in comments, it's better to separate values to chunks and then sort each part then join parts again. If nesting depth is only one level you can use default sort (without _sort function) but be aware of array in array used for nested array. So the sort should be changed like this:
chunks.forEach(ch => Array.isArray(ch[0])? ch[0].sort(): ch.sort());

Remove multiple elements from array by value in JS

When I want to remove one element, it is easy. This is my function:
function removeValues(array, value) {
for(var i=0; i<array.length; i++) {
if(array[i] == value) {
array.splice(i, 1);
break;
}
}
return array;
}
But how do I remove multiple elements?
Here a simple version using ES7:
// removing values
let items = [1, 2, 3, 4];
let valuesToRemove = [1, 3, 4]
items = items.filter((i) => !valuesToRemove.includes(i))
For a simple version for ES6
// removing values
let items =[1, 2, 3, 4];
let valuesToRemove = [1, 3, 4]
items = items.filter((i) => (valuesToRemove.indexOf(i) === -1))
const items = [0, 1, 2, 3, 4];
[1, 4, 3].reverse().forEach((index) => {
items.splice(index, 1)
})
// [0, 2, 4]
I believe you will find the kind of functionality you are looking for in Javascript's built in array functions... particularily Array.map(); and Array.filter();
//Array Filter
function isBigEnough(value) {
return value >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]
//Array Map (Can also be used to filter)
var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
return num * 2;
});
// doubles is now [2, 8, 18]. numbers is still [1, 4, 9]
/////UPDATE REFLECTING REMOVAL OF VALUES USING ARRAY MAP
var a = [1,2,3,4,5,6];
a.map(function(v,i){
if(v%2==0){
a.pop(i);
}
});
console.log(a);
// as shown above all array functions can be used within the call back to filter the original array. Alternativelty another array could be populated within the function and then aassigned to the variable a effectivley reducing the array.

difference between two arrays with javascript filter

Problem:
Compare two arrays and return a new array with any items not found in both of the original arrays. Use Array.filter and Array.indexOf to solve this.
function diff(arr1, arr2) {
var newArr = [];
//code here
return newArr;
}
diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);
I am not sure how to proceed. My solution is different from the above and uses a hard coded array. How do I make mine generic ?
function arrayNotContains(element){
var arr = [1, 2, 3, 5];
if(arr.indexOf(element) === -1){
return true;
}else{
return false;
}
}
var filtered = [1, 2, 3, 4, 5].filter(arrayNotContains);
console.log(filtered);
I got one more solution below. Is that ok ?
var arr1 = [1,2,3,5];
var arr2 = [1,2,3,4,5];
var filtered = arr2.filter(function(num) {
if (arr1.indexOf(num) === -1) return num;
});
You will want to use a closure:
function notContainedIn(arr) {
return function arrNotContains(element) {
return arr.indexOf(element) === -1;
};
}
var filtered = [1, 2, 3, 4, 5].filter(notContainedIn([1, 2, 3, 5]));
console.log(filtered); // [4]
Notice this is just a generalised version of your solution, I'm not saying that this is actually a valid solution for a symmetric diff function. For that, as it was stated in your problem, you'd need to do something like
function symmDiff(a, b) {
return a.filter(notContainedIn(b)).concat(b.filter(notContainedIn(a)));
}

Categories