Find a value by key from array of objects [duplicate] - javascript

This question already has answers here:
Find object by id in an array of JavaScript objects
(36 answers)
Closed last month.
I have an huge array of object and need to find the name of object by key, how can I do that with the optimized way.
const key = 2;
const arr = [ {id: 1, text: '1111'}, {id: 2, text: '2222'}, {id: 3, text: '333'},]
I need to return only the text '2222'
The original array have an 154 object thats why I need the most optimized way.
arr.forEach((obj) => {
Object.keys(obj).forEach((key) => {
console.log("key : " + key + " - value : " + obj[key]);
});
});

JavaScript has great array methods to do these kind of things. In your case I would use array.find to achieve what you're after. You can read more about it here
const key = 2;
const arr = [ {id: 1, text: '1111'}, {id: 2, text: '2222'}...]
const result = arr.find((item) => item.id === key).text;
console.log(result) // will print '2222'

You can do it using forEach or for loop
In term of optimisation for loop is the fastest one
var key = 2;
const arr = [ {id: 1, text: '1111'}, {id: 2, text: '2222'}, {id: 3, text: '333'},]
arr.forEach((obj) => {
if (obj.id == key) {
console.log(obj.text);
}
});
for (let i = 0; i < arr.length; i++) {
if (arr[i].id == key) {
console.log(arr[i].text)
}
}

Related

Efficient way to get unique objects from array of objects, by object property?

Here is my array of objects
const array = [
{id: 1, data: "foo"},
{id: 1, data: "bar"},
{id: 2, data: "baz"}
]
I want to remove all duplicate objects by its id and return only the array of objects that have an unique id.
Expected result:
[
{id: 2, data: "baz"}
]
This is what I have now: O(n^2)
function getUnique(array) {
const newArray = []
for (let obj of array) {
if (array.filter(x => x.id === obj.id).length === 1) {
newArray.push(obj)
}
}
return newArray
}
Whats the more efficient way to achieve this?
Is it possible to get the time-complexity to O(n) or O(n log n)?
const array = [{
id: 1,
data: "foo"
},
{
id: 1,
data: "bar"
},
{
id: 2,
data: "baz"
}
]
let map = {};
array.forEach(x => {
map[x.id] = (map[x.id] || 0) + 1
});
console.log(array.filter(x => map[x.id] === 1))
I would suggest to count the number of occurrences in your array and store them in a Map. Next you filter all element, which count is 1
function getUnique(arr) {
const count = new Map();
arr.forEach((element) => {
count.set(element.id, (count.get(element.id) || 0) + 1);
});
return array.filter((element) => {
return count.get(element.id) === 1;
});
}
This has a runtime of 2(n) since you have to iterate over them twice

Replace item in array of objects with Javascript

I have an array of objects like this:
const myArr = [{id: 1, ...}, {id: 2, ...}, {id: 3, ...}];
and I have an object like this:
const myObj: {id: 2, someNewField};
I want to replace this new object for the one with the same ID in the original array, how can I do this?
I tried doing it like this:
const index = myArr.findIndex(item => item.id === myObj.id);
const filteredArr = myArr.filter(item => item.id !== myObj.id);
filteredArr.splice(index, 0, myObj);
It works but maybe there's a better way to do it
Instead of finding the index and filtering you could always use .map to return a new array.
const myObj = { id: 2, new: 1 };
const myArr = [{ id: 1 }, { id: 2 }, { id: 3 }];
const newArr = myArr.map(v => {
return v.id === myObj.id ? myObj : v;
});
It depends on what you would like to do if the item is not found in the array, as this will only replace.
By better if you mean faster method, here is one,
for(let i = 0;i<myArr.length; i++) {
if(myArr[i].id === myObj.id) {
myArr[i] = myObj;
break;
}
}
This is faster than your method because we are using for loop instead of .filter() or .findIndex() which is slower than regular for loop.
If you mean the most compact then you can do this,
myArr[myArr.findIndex(item => item.id === myObj.id)] = myObj;
Note that this approach will fail if there is no item with the given object key.

Struggling to loop through an array of objects

in particular I want to access answer's numerical value, so that later on to sum them up.
previously tried length, which is not working for objects.
here is my data:
const qData = [
{
id: 0,
question: "question 1",
answers: [
{ value: 1, text: "rafael" },
{ value: 2, text: "dontaelo" },
{ value: 3, text: "leonardo" },
{ value: 4, text: "michelangelo" }
]
},
{
id: 1,
question: "question 2",
answers: [
{ value: 1, text: "rafael" },
{ value: 2, text: "dontaelo" },
{ value: 3, text: "leonardo" },
{ value: 4, text: "michelangelo" }
]
}
];
export default qData;
I attempted to sum the answer values like so:
handleShowScore = () => {
var i, newScore;
var a = qData.answers;
for (i = 0; i < a.length; i++) {
newScore = newScore + a[i].value;
}
}
qData is an array and doesn't have the property answers, so qData.answers will not work and return undefined.
You first have to loop over the questions, then in each question you'll have to loop over the answers:
const qData = [{id:0,question:"question 1",answers:[{value:1,text:"rafael"},{value:2,text:"dontaelo"},{value:3,text:"leonardo"},{value:4,text:"michelangelo"}]},{id:1,question:"question 2",answers:[{value:1,text:"rafael"},{value:2,text:"dontaelo"},{value:3,text:"leonardo"},{value:4,text:"michelangelo"}]}];
let sum = 0;
for (const question of qData) {
for (const answer of question.answers) {
sum += answer.value;
}
}
console.log(sum);
You could do this reduce the amount of loops if you use flatMap. Pulling up the answers into one large array.
const qData = [{id:0,question:"question 1",answers:[{value:1,text:"rafael"},{value:2,text:"dontaelo"},{value:3,text:"leonardo"},{value:4,text:"michelangelo"}]},{id:1,question:"question 2",answers:[{value:1,text:"rafael"},{value:2,text:"dontaelo"},{value:3,text:"leonardo"},{value:4,text:"michelangelo"}]}];
const answers = qData.flatMap(question => question.answers);
let sum = 0;
for (const answer of answers) {
sum += answer.value;
}
console.log(sum);
Instead of using a for loop to sum the values you could also use reduce, which iterates over an array reducing it to a single value.
const qData = [{id:0,question:"question 1",answers:[{value:1,text:"rafael"},{value:2,text:"dontaelo"},{value:3,text:"leonardo"},{value:4,text:"michelangelo"}]},{id:1,question:"question 2",answers:[{value:1,text:"rafael"},{value:2,text:"dontaelo"},{value:3,text:"leonardo"},{value:4,text:"michelangelo"}]}];
const answers = qData.flatMap(question => question.answers);
const sum = answers.reduce((sum, answer) => sum + answer.value, 0);
console.log(sum);
The sample below does what you want, if I understood your question correctly
// Loop through all questions. Each question is stored in "q".
qData.forEach((q) => {
console.log('qData:', q);
​
// Make an array of all answer values
const answerValues = q.answers.map((a) => {
return a.value;
});
console.log('answerValues:', answerValues);
​
// Sum all answer values together
const totalValues = answerValues.reduce((a, b) => a + b, 0)
console.log('totalValues: ', totalValues);
});
If you want to have the sum of a specific ID
// Find specific ID.
const question = qData.find((q) => q.id === 0);
// Make an array of all answer values
const answerValues = question.answers.map((a) => {
return a.value;
});
console.log('answerValues:', answerValues);
// Sum all answer values together
const totalValues = answerValues.reduce((a, b) => a + b, 0)
console.log('totalValues: ', totalValues);
It's kind of a quiz, right? Let's assume my answers are:
const myAnswers = [{question: 'question 1', myAnswer:'rafael'},{question: 'question 2', myAnswer:'dontaelo'}]
I should have 1 point from the first question, and 2 from the second. We need to go through 2 loops: 1 to find the corresponding question, 1 to find the corresponding number of points:
const myPoints = myAnswers.map(answer => qData.find(question => question.question === answer.question).answers.find(possibleAnswer => possibleAnswer.text === answer.myAnswer).value)
Thats gives me [ 1, 2 ]. Now we need to to the sum with reduce:
const reducer = (accumulator, currentValue) => accumulator + currentValue;
const myScore = myPoints.reduce(reducer, 0);
I have 3 points ;-)

How can I check if the array of objects have duplicate property values with more properties?

I have searched StackOverflow and found this answer, but it does not solve my problem.
My problem is, my array is like this:
let arr = [
{type: 1, id: 1, name:'aa'},
{type: 1, id: 1, name:'bb'},
{type: 2, id: 1, name:'cc'}
]
And I need to find same type and same id and then recognize that this is duplicate object. Above, arr[0] and arr[1] is a duplicate but arr[0] and arr[2] are not. I have tried using ES6 methods such as .some(), .every(), and a Set(), but non of these have worked for me. How can I solve this problem?
You can use .map() to map each object to a string. Each string takes the shape of type-id for that object. Then, using a Set you can remove all duplicate strings. You can then check if the set size equals the array length to determine if there are any duplicates or not in the array:
const containsDups = arr => new Set(arr.map(({type, id}) => `${type}-${id}`)).size !== arr.length;
const arr = [{type: 1, id: 1, name:'aa'},{type: 1, id: 1, name:'bb'},{type: 2, id: 1, name:'cc'}];
console.log(containsDups(arr));
It is possible to group by properties such as type and id and then check whether names more than 1. If yes, it means, that there is at least one duplicate:
const result = [...arr.reduce((r, o) => {
const key = o.type + '-' + o.id;
const item = r.get(key) || Object.assign({}, o, {
names: []
});
item.names.push(o.name);
return r.set(key, item);
}, new Map).values()];
An example:
let arr = [{type: 1, id: 1, name:'aa'},{type: 1, id: 1, name:'bb'},{type: 2, id: 1, name:'cc'}]
const result = [...arr.reduce((r, o) => {
const key = o.type + '-' + o.id;
const item = r.get(key) || Object.assign({}, o, {
names: []
});
item.names.push(o.name);
return r.set(key, item);
}, new Map).values()];
console.log(`Is there duplicates: `, result.some(s => s.names.length > 1));
you can use Set:
Set is a new data object introduced in ES6. Because Set only lets you store unique values
const seen = new Set();
const arr = [
{type: 1, id: 1, name:'aa'},
{type: 1, id: 1, name:'bb'},
{type: 2, id: 1, name:'cc'}
];
const filteredArr = arr.filter((el, index) => {
const duplicate = seen.has(el.type, el.id);
seen.add(el.type, el.id);
console.log('index: '+ index +' is duplicate: '+ duplicate);
return !duplicate; // if you just need a boolean, this is what you are looking for.
});
console.log('new array: ' + JSON.stringify(filteredArr));

Remove object from array knowing its id [duplicate]

This question already has answers here:
How can I remove a specific item from an array in JavaScript?
(142 answers)
Closed 7 years ago.
I have an array of objects:
var myArr;
Let’s say that on page load it contains 10 objects with the following structure:
{
Id: …,
Name: …
}
How can I remove an object from myArr by its Id?
Try like this
var id = 2;
var list = [{
Id: 1,
Name: 'a'
}, {
Id: 2,
Name: 'b'
}, {
Id: 3,
Name: 'c'
}];
var index = list.map(x => {
return x.Id;
}).indexOf(id);
list.splice(index, 1);
console.log(list);
JSFIDDLE
Or you can utilize .filter()
Like this
var id = 2;
var list = [{
Id: 1,
Name: 'a'
}, {
Id: 2,
Name: 'b'
}, {
Id: 3,
Name: 'c'
}];
var lists = list.filter(x => {
return x.Id != id;
})
console.log(lists);
DEMO
Two solutions, one evolve creating new instance and one changes the instance of your array.
Filter:
idToRemove = DESIRED_ID;
myArr = myArr.filter(function(item) {
return item.Id != idToRemove;
});
As you can see, the filter method returns new instance of the filtered array.
Second option is to find the index of the item and then remove it with splice:
idToRemove = DESIRED_ID;
index = myArr.map(function(item) {
return item.Id
}).indexOf(idToRemove);
myArr.splice(index, 1);
can you try
newArray = myArr
.filter(function(element) {
return element.id !== thisId;
});

Categories