Find and Change specific item from an object array - javascript

I'm dealing with an array like
arr = [{id:'first',name:'John'},{id:'fifth',name:'Kat'},{id:'eitghth',name:'Isa'}]. Now i want to give condition to the array like if i get id 'fifth' in array, The array will change to
arr = [{id:'first',name:'John'},{id:'sixth',name:'Kat'},{id:'eitghth',name:'Isa'}]
Like just one part of an item is modified. How can i do that in js?

You can use Array.prototype.find to locate the entry, and then simply update its id attribute:
const arr = [{id:'first',name:'John'},{id:'fifth',name:'Kat'},{id:'eitghth',name:'Isa'}];
const entry = arr.find(item => item.id === 'fifth');
entry.id = 'sixth';
console.log(arr);
You can also use Array.prototype.findIndex to retrieve the index of the entry that you want to replace, and modify it accordingly:
const arr = [{id:'first',name:'John'},{id:'fifth',name:'Kat'},{id:'eitghth',name:'Isa'}];
const targetIndex = arr.findIndex(item => item.id === 'fifth');
arr[targetIndex].id = 'sixth';
console.log(arr);
However, the two methods above only help to find the first matching element. If you have multiple entries in the array with the ID of fifth, then you are better off using iteration:
const arr = [{id:'fifth',name:'Kat'},{id:'fifth',name:'Kat'},{id:'fifth',name:'Kat'}];
arr.forEach(item => {
if (item.id === 'fifth') {
item.id = 'sixth';
}
});
console.log(arr);

Related

How to check if values in array is present in object key of object array

I want to check if values in one array is present in object key of object array.
For example: arr = ["id1", "id2"]
objectArr = [{id: "id1"}]
I want to throw not found error in this case when id2 is not present in id of object array.
Help of any kind would be appreciated!
You can use filter and some for that:
var objectArr = [{id: "id1"}, {id: "id3"}]
var arr1 = ["id1", "id2"];
const notFounds = arr1.filter(el => !objectArr.some(obj => obj.id === el ));
console.log(notFounds); // ["id2"]
JS Array some:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some
JS Array filter:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
If You iterate over objectArr, You can get object fields in form of array with: Object.entries(your_object).
for (const obj of objectArr) {
for (const item of Object.entries(obj)) {
// where item is field in object
// now You can compare if item is in [id1,id2]
}
}
You can try something like this
var arr = ["id1", "id2", "id3", "id4"];
var n = arr.includes("id2"); //true
For an array of objects. If the id is unique in the array
var arr = [{id:"id1"},{id:"id2"},{id:"id3"},{id:"id4"}]
const found = arr.some(el => el.id === "id3") // true
EDIT: ran.t has a better answer that keeps track of which ids are not found.
It sounds like what you're looking for is .every() method. Which will allow you can check each element in the array passes a given condition.
You can combine this with the .some() method to check at least one object in the objectArr has id equal to your element
const allElementsFound = ["id1", "id2"].every(el => objectArr.some(obj => obj.id === el))
if(!allElementsFound) {
// throw error
}

Return only value of listed index from an array JavaScript

I'm trying to filter an array based on the listed index in another array.
For example:
const item = ['apple','orange','watermelon','pineapple'];
const index = [1,3];
Based on the index array , I want to return an array of [ 'orange','pineapple']
How do I do that in an efficient way? I tried using comparison between 2 array , but i think it is not very good for efficiency.
You can do map over the index array and just do a regular indexing to look up the item from the item array.
const result = index.map(idx => item[idx]);
No need for comparisons when you already have the indices. You just access them directly instead.
You can do something like this:
const filteredArray = index.map(i => item[i]);
Output:
You can do the following,
const res = [];
item.forEach((item, idx) => { if(index.includes(idx)) res.push(item); });
console.log(res);

.filter not working on array with objects in javascsript

I want to filter items array such that theItem with productid "b" is removed from the items array, so that only items with prdocutid a and c remain, but the filter is not working !
const items = [{productid:'a'}, {productid:'b'}, {productid:'c'}];
const theItem = {productid:'b'};
items.filter( item => item.productid === theItem.productid);
items.forEach(element => console.log(element));
filter() does not modify the variable itself. Instead, it returns a new list/array of the result. Here is the documentation.
Here is the solution to your question:
const items = [{ productid:'a' }, { productid:'b' }, { productid:'c' }];
const theItem = { productid:'b' };
// assigning the value to a variable
const results = items.filter(item => item.productid === theItem.productid);
results.forEach(element => console.log(element));
Output: {productid: "b"}
Array.prototype.filter() returns a new filtered array, it does not mutate the original array. You need to modify your code like this:
Method - 1:
Change the original array items to let instead of const so you can save the result from filter into items then iterate over items:
//Changed from const to let so I can save the filtered array into this array
let items = [{productid:'a'}, {productid:'b'}, {productid:'c'}];
const theItem = {productid:'b'};
//Store the resultant array from filter into the original array
items = items.filter( item => item.productid === theItem.productid);
items.forEach(element => console.log(element));
Method - 2:
Store the filtered array in a new Array:
const items = [{productid:'a'}, {productid:'b'}, {productid:'c'}];
const theItem = {productid:'b'};
//Store the resultant array from filter into a new array
const filteredItems = items.filter( item => item.productid === theItem.productid);
filteredItems.forEach(element => console.log(element));

How to compare a part of an array item with a part of an array item from a second array?

If I have two arrays with files
arr1 = ['file1.webp', 'file2.webp', ...];
arr2 = ['file1.jpg', 'file2.png', 'file3.jpg', 'file4.jpg', ...];
how would I check which array items are equal, minus the *.format part?
The idea is that, if there are two equal items, a webp and an alternative source are available. While if an item has no match, no webp source was provided. Both cases would lead to different image handling later on.
I could compare the items inside two arrays like so: let match = arr1.find( val => arr2.includes(val) );
But this compares each entire item. I only want to compare the file names. The formats in which the files were provided need to be cut off, so I get:
arr1 = ['file1', 'file2', ...];
arr2 = ['file1', 'file2', 'file3', 'file4', ...];
I can then filter out all matches between the two arrays. I've been searching for a solution for a real while, but I'm still not sure how to get there.
With a function that trims off the file extension, you can construct a Set of one of the transformed arrays. Then iterate over the other array and check whether its transformed item is in the Set or not:
const arr1 = ['file1.webp', 'file2.webp'];
const arr2 = ['file1.jpg', 'file2.png', 'file3.jpg', 'file4.jpg'];
const transform = str => str.replace(/\.[^.]+$/, '');
const set1 = new Set(arr1.map(transform));
for (const item of arr2) {
if (set1.has(transform(item))) {
console.log('Match for', item);
} else {
console.log('No match for', item);
}
}
You can use filter() with nested some(). To get the file name from complete name use split('.')and get the first element using .split('.')[0]
let arr1 = ['file1.webp', 'file2.webp'];
let arr2 = ['file1.jpg', 'file2.png', 'file3.jpg', 'file4.jpg'];
let res = arr2.filter(a => arr1.some(b => a.split('.')[0] === b.split('.')[0]));
console.log(res)
You could filter by looking to the right side.
const getName = s => s.replace(/\.[^.]+$/, '');
var array1 = ['file1.webp', 'file2.webp'],
array2 = ['file1.jpg', 'file2.png', 'file3.jpg', 'file4.jpg'],
set1 = new Set(array1.map(getName)),
common = array2.filter(s => set1.has(getName(s)));
console.log(common);
write extract method to get value to compare. Just use the extract method in your code. Alternatively, you can build an arr2Obj to not to repeat the searches.
const arr1 = ["file1.webp", "file2.webp"];
const arr2 = ["file1.jpg", "file2.png", "file3.jpg", "file4.jpg"];
const extract = item => item.split(".")[0];
let match = arr1.find(val => arr2.map(x => extract(x)).includes(extract(val)));
console.log(match);
// Alternatively,
const arr2Obj = Object.assign({}, ...arr2.map(x => ({ [extract(x)]: 1 })));
const match2 = arr1.find(val => extract(val) in arr2Obj);
console.log(match2);

Get objects in array with duplicated values

I need to get elements from an array of objects where one of that object's properties (name in this case) is duplicated--in other words, appears in some other object in the array.
data
var data = [
{id:1, name:"sam", userid:"ACD"},
{id:1, name:"ram", userid:"SDC"},
{id:1, name:"sam", userid:"CSTR"}
];
i need to check all row and get all the array value where name property is duplicating.
the expected output:
[
{id:1, name:"sam", userid:"ACD"},
{id:1, name:"sam", userid:"CSTR"}
]
my code
Array.from(data).map(x => x.name)
but it is returning all the values.
The code should not create any performance issue because array will contain more than 500 rows.
Angular is a framework, not a language. There is no Angular in your problem.
Let me understand if I understood well. You have an array of objects and you want to keep all the elements that are duplicate and get rid of others, all right? You can try:
data.reduce((acc, value, i, arr) => {
if(acc.some(v => v.name === value.name)) return acc;
let filtered = arr.filter(v => v.name === value.name);
return filtered.length > 1 ? acc.concat(filtered) : acc;
}, []);
Or you can sort your array in first instance, in order to improve performance:
const sort = (a, b) => a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1;
let duplicates = [];
let sortedArray = data.sort(sort);
for(let i=0; i<sortedArray.length - 1; i++) {
if(sortedArray[i].name === sortedArray[i+1].name) {
duplicates.push(sortedArray[i], sortedArray[i+1]);
i++;
}
}
The brute force approach would be to filter the array to keep only those elements with duplicated names, as expressed by the filter function duplicateName.
// Is there more than one element in an array satisfying some predicate?
const hasMultiple = (arr, pred) => arr.filter(pred).length > 1;
// Is this element a duplicate in the context of the array?
const duplicateName = (elt, idx, arr) => hasMultiple(arr, e => e.name === elt.name);
// Test data.
var data = [
{id:1,name:"sam", userid:"ACD"},
{id:1,name:"ram", userid:"SDC"},
{id:1,name:"sam", userid:"CSTR"}
];
console.log(data.filter(duplicateName));
However, this is going to have poor performance (O(n^2)) in the case of many elements. To solve that problem, you're going to need to preprocess the array. We'll create an object with a property for each name, whose value is an array of all the elements in which that name occurs. This operation is usually called groupBy. Several popular libraries such as underscore will provide this for you. We'll write our own. After grouping, we will filter the object of groups to remove those with only one member.
// Group an array by some predicate.
const groupBy = (arr, pred) => arr.reduce((ret, elt) => {
const val = pred(elt);
(ret[val] = ret[val] || []).push(elt);
return ret;
}, {});
// Filter an object, based on a boolean callback.
const filter = (obj, callback) => Object.keys(obj).reduce((res, key) => {
if (callback(obj[key], key, obj)) res[key] = obj[key];
return res;
}, {});
// Remove groups with only one element.
const removeNonDups = groups => filter(groups, group => group.length > 1);
// Test data.
var data = [
{id:1,name:"sam", userid:"ACD"},
{id:1,name:"ram", userid:"SDC"},
{id:1,name:"sam", userid:"CSTR"}
];
console.log(removeNonDups(groupBy(data, elt => elt.name)));

Categories

Resources