I am little confused on how to compare two array objects' particular value get that neglected values as an array.
var Arr1 = [
{
jobId:"j1"
},
{
jobId:"j2"
},
{
jobId:"j3"
},
{
jobId:"j4"
},
]
var Arr2 = [
{
jobId:"j1"
},
{
jobId:"j2"
},
]
I want my result like this...
//neglected values
[
{
jobId:"j3"
},
{
jobId:"j4"
},
]
So let's think about how to go about comparing things in two arrays.
It probably makes sense to assume in order to fully compare both arrays, we need to iterate them, making sure we compare every item in each array so that we can be sure
So if I was begining i would think of nesting for - loops. Why? Because it will iterate over the first array, on each index it hits the first array, it will then iterate over every element in the second array.
then you can create some basic if conditional logic like if Arr1[i] === Arr2[j], push one of the objects into an array.
Filter (Array#filter) down the elements of the first array to those for which there are not (!) some (Array#some) matching job IDs in the second array.
Arr1.filter(arr1Elt => !Arr2.some(arr2Elt => arr2Elt.jobId === arr1Elt.jobId))
Using line-by-line comment style:
Arr1 // From Arr1,
.filter( // keep
arr1Elt => // elements for which
! // it is not the case that
Arr2 // Arr2 has
.some( // some
arr2Elt => // elements for which
arr2Elt.jobId // the job ID
=== // is equal to
arr1Elt.jobId // the job ID from the first array.
)
)
You can use lodash's _.differenceBy() to find the items from Arr1 missing from Arr2.
var Arr1 = [{"jobId":"j1"},{"jobId":"j2"},{"jobId":"j3"},{"jobId":"j4"}];
var Arr2 = [{"jobId":"j1"},{"jobId":"j2"}];
// find items that are in Arr1, but not in Arr2, compare items by their jobId
var result = _.differenceBy(Arr1, Arr2 , 'jobId');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.3/lodash.min.js"></script>
You can use Array.prototype.filter on Arr1 and check if any of its entries are in Arr2 using Array.prototype.some - see demo below:
var Arr1=[{jobId:"j1"},{jobId:"j2"},{jobId:"j3"},{jobId:"j4"}];
var Arr2=[{jobId:"j1"},{jobId:"j2"}];
var result = Arr1.filter(function(e){
return !Arr2.some(function(k){
return k.jobId === e.jobId;
});
});
console.log(result);
Related
I know that if there is an array of values it must be used this approach:
console.log(['joe', 'jane', 'mary'].includes('jane')); // true
But in case of an array of arrays, is there a short way to do it? Without other computations between.
For this input:
[['jane'],['joe'],['mary']]
You can use flat method to flatten the array. For more neted array, you can also mention depth like flat(depth)
let arr = [["jane"],["joe"],["mary"]];
arr.flat().includes('jane'); //true
You can easily achieve this result using some
arr.some((a) => a.includes("jane"))
const arr = [
["jane"],
["joe"],
["mary"]
];
const arr2 = [
["joe"],
["mary"]
];
console.log(arr.some((a) => a.includes("jane")));
console.log(arr2.some((a) => a.includes("jane")));
it can also be done by first flattening the 2d arrays in 1 d aaray and then using includes to find whether the array contains the element or not
var arr = [['jane'],['joe'],['marry']]
var newarr=[].concat(...arr)
var v=newarr.includes('jane')
console.log(v)
I have an array like below:
[
'author/2020/01/01/all_authors_000.csv',
'book/2020/01/01/all_books_000.csv',
'book/2020/01/01/all_books_001.csv',
'book/2020/01/01/all_books_002.csv',
'others/2020/01/01/other_stuff.csv',
]
As you can see there are three items that start with the word book. I want to remove all but one, so I end up with something like:
[
'author/2020/01/01/all_authors_000.csv',
'book/2020/01/01/all_books_000.csv',
'others/2020/01/01/other_stuff.csv',
]
How can I achieve this?
Here is working example:
var array = [
"author/2020/01/01/all_authors_000.csv",
"book/2020/01/01/all_books_000.csv",
"book/2020/01/01/all_books_001.csv",
"book/2020/01/01/all_books_002.csv",
"others/2020/01/01/other_stuff.csv",
];
var filteredArray = [];
var previous = "";
for (let i of array) {
if (i.substr(0, i.indexOf("/")) != previous) {
filteredArray.push(i);
previous = i.substr(0, i.indexOf("/"));
}
}
Every loop the value before "/2020" is stored inside the previous variable, and the if statement checks, if the value is the same as in the previous loop. If not, it pushes it into the filteredArray.
Therefore filteredArray is the array without duplicates.
Here is another method of doing it. Basically a function that takes in your array and a criteria to identify duplicates (in your case book). All of these duplicates will be removed but the first one.
const array = [
"author/2020/01/01/all_authors_000.csv",
"book/2020/01/01/all_books_000.csv",
"book/2020/01/01/all_books_001.csv",
"book/2020/01/01/all_books_002.csv",
"others/2020/01/01/other_stuff.csv",
];
const removeDuplicates = (array, criteria) => {
return array.filter(
(path) =>
![...array.filter((path) => path.includes(criteria)).splice(1)].includes(
path
)
);
};
console.log(removeDuplicates(array, "book"));
Say I have
arr1 = ["Tom","Harry","Patrick"]
arr2 = ["Miguel","Harry","Patrick","Felipe","Mario","Tom"]
How can I remove the duplicate elements in arrays?
I want this output
arr2 = ["Miguel","Felipe","Mario"]
Use filter combined with includes. Example:
let arr1 = ["Tom","Harry","Patrick"]
let arr2 = ["Miguel","Harry","Patrick","Felipe","Mario","Tom"]
arr2 = arr2.filter(x=>!arr1.includes(x))
console.log(arr2)
I think that the best way will be to use filter() array method, iterate through the target array (it's arr2 in this case), and exclude duplicates via !arr1.includes(currentItem). This construction lets you know, does arr1 contain current item of iteration:
const arr1 = ["Tom","Harry","Patrick"];
const arr2 = ["Miguel","Harry","Patrick","Felipe","Mario","Tom"];
const result = arr2.filter(d => !arr1.includes(d));
console.log(result);
If you have lodash, you can use the difference function directly.
_.difference(arr2, arr1) will give the required output.
Edit: JSFiddle URL: https://jsfiddle.net/k3ynjq1m/3/
Using includes() is better because returns true or false, but unfortunately it is not supported by IE, see this. In case you want this working on IE too, you should use indexOf().
var arr1 = ["Tom","Harry","Patrick"]
var arr2 = ["Miguel","Harry","Patrick","Felipe","Mario","Tom"]
arr2 = arr2.filter(e=>arr1.indexOf(e)<0)
console.log(arr2)
And filter is better because:
The filter() method creates a new array with all elements that pass
the test implemented by the provided function.
Using regular js, you can use a nested for loop:
for (var i in arr2) {
var duplicate = false;
for (var i2 in arr1) {
if (arr2[i] == arr1.[i2]) {
duplicate = true;
}
}
if (duplicate) {
arr2.splice(i, 1);
}
}
I think you should keep a map and add elements to that map.
if element exists in map, then that is duplicate else add it to map.
The way you can store your duplicates is storing their value in another list. That is up to you.
Once you know your duplicates, duplicate it from the list.
This is O(n) complexity, and O(n) space complexity.
for(var i = 0 ; i<this.arr1.length; i++) {
for(var j = 0 ; j<this.arr2.length; j++) {
if(this.arr1[i] === this.arr2[j]) {
this.arr1.splice(i, 1);
this.arr2.splice(j, 1);
i--;
j--;
}
}
}
this.arr2 = this.arr1.concat(this.arr2);
console.log(this.arr2)
here's a working code (your exemple): https://stackblitz.com/edit/angular-yzte87
So the way I see it there are multiple ways to achieve what you're looking for,
Using filter and include like some mentioned above me -
It will work but I don't know how efficient that will be as you are using filter to iterate on arr2 and then for each element you iterate on arr1 to see if there's matching case, I don't know how familiar you are with algorithm analysis but it's O(N power 2) which is not very time efficient, means quickly as arr1 or arr2 will grow it will take much longer for your function to run, if you do go with that option please use sort() first so you might save time and be more efficient.
See Example:
let namesToRemove = ["Tom", "Harry", "Patrick"].sort()
let names = ["Miguel", "Harry", "Patrick", "Felipe", "Mario", "Tom"].sort()
let lastNameToRemove = namesToRemove[namesToRemove.length - 1]
names = names.filter((name) => {
if (name[0] > lastNameToRemove[0]) {
return true
}
return !namesToRemove.includes(name)
})
console.log(names)
Keep in mind that if you will use for loop and splice() you can just break and it will be even more efficient.
Using Map - You can iterate once on your first array and create a map in JS which is just using an object notation and once on your names array and check if there is a match, you can improve that using sort() and other improvement but the idea is, see below example.
See Example:
let namesToRemove = ["Tom", "Harry", "Patrick"]
let names = ["Miguel", "Harry", "Patrick", "Felipe", "Mario", "Tom"]
let namesToRemoveMap = {}
for (name of namesToRemove) {
namesToRemoveMap[name] = true
}
names = names.filter((name) => !namesToRemoveMap[name])
console.log(names)
Of course either way you choose I would include some more defensive checks, like if the arrays have value in them etc...
Hope I could explain myself clear, let me know if you need more help or if you have any question.
So you want to remove elements from an array (if they exist) based from another array.
Ok, let see... I have a component that implement a function with a similar logic:
let criteriaArr = ["Tom", "Harry", "Patrick"];
let arrToFilter = ["Miguel","Harry","Patrick","Felipe","Mario","Tom"];
let filteredArray = arrToFilter.filter(e => criteriaArr.indexOf(e) < 0);
console.log(filteredArray);
So what filter does is: Returns the elements of an array that meet the condition specified in a callback function.
what the callback function does is: for each element from arrToFilter, if that element does not exit in criteriaArr then keep it otherwise go to the next element.
Here is the function:
removeElems(arrToFilter: Array<any>): Array<any> {
let filteredArray = arrToFilter.filter(e => this._criteriaArr.indexOf(e) < 0);
return filteredArray;
}
this._criteriaArr is a private property with default value: private _criteriaArr = ["Tom","Harry","Patrick"]
Or, you can do it this way:
removeElems(arrToFilter: Array<any>, criteriaArr: Array<any>): Array<any> {
let filteredArray = arrToFilter.filter(e => criteriaArr.indexOf(e) < 0);
return filteredArray;
}
handle it with two array.
have fun ! :)
I’ve got a "2D"-JavaScript array, holding these kind of data:
let arr = [
["w",0],
["x",1],
["y",0],
["z",2]
]
I would like to remove all rows that contain a 0 for their second item, so that the resulting array would look like this:
arr = [
["x",1],
["z",2]
]
Any elegant thoughts?
Use Array.filter() where you can check the inner array do not contain element value 0 on second position by item[1] !== 0:
let arr = [
["w",0],
["x",1],
["y",0],
["z",2]
];
var res = arr.filter(item => item[1] !== 0);
console.log(res);
Using filter() you can loop through each element of the array and pass that element in a callback function which then return the same/modified element based on the condition. So, item is the element of the array and this is passed to a callback function. Since, we have only one line code in callback we can replace that callback function with item[1] !== 0 and it also return by default when the condition is satisfied.
A solution with Array.prorotype.filter and array destructuring assignment:
let arr = [
["w",0],
["x",1],
["y",0],
["z",2]
]
const filtered = arr.filter(([_,a]) => a > 0);
console.log(filtered);
I want to merge two different array of objects which having one same key value.
here are my two array of objects.
arr1 = [{id:1,name:'amit',age:23},{id:2,name:'akash',age:24},{id:3,name:'arun',age:22}];
arr2 = [{id:1, add : 'india'},{id:3, add:'india'},{id:2,add:'india'}];
I want to merge these two array into one array with complete data .
arr3 = [{id:1,name:'amit',age:23, add:'india'},{id:2,name:'akash',age:24, add:'india'},{id:3,name:'arun',age:22,add:'india'}];
i try to do this but could not get the desired result.
var arr3 = _.map(arr1, function(item){
return _.extend(item, _.findWhere(arr2, { id: item.id }));
});
there can be some empty array which can cause changes.
i want to avoid two for loops and then one if condition because it will increase complexity. if anyone have better solution for this.
thanks in advance.
This will give the desired result.
_.each will iterate the arr3 and perform the action.
// copies arr1 to arr3
var arr3 = Array.from(arr1);
_.each(arr3, (item) => {
// extends another object to the current object (item from arr3)
_.extend(item, _.find(arr2, (a) => a.id == item.id));
})
We will get the desired result in arr3
You can use loadash merge
var arr3 = _.merge(arr1, arr2)