I'm trying to check if an array within an object contains an element userAnswer or not. Is there a good way to do this using es6. I've tried a few however, I can't seem to get it to work properly. Most of my attempts return an error. Any help would be appreciated.
Last Attempt
conductedExam.questions.some(question => question.userAnswer.includes(Object))
Data
{
_id: '1',
questions: [
{ name: '1', userAnswer: 'one' },
{ name: '2', userAnswer: 'two' },
{ name: '2' }
]
};
Use hasOwnProperty:
const conductedExam = {
_id: '1',
questions: [
{ name: '1', userAnswer: 'one' },
{ name: '2', userAnswer: 'two' },
{ name: '2' }
]
};
console.log(conductedExam.questions.some(e => !e.hasOwnProperty("userAnswer")));
Using hasOwnProperty might work.
conductedExam.questions.some(question => question.hasOwnProperty('userAnswer')) returns true
Related
in an arry of objects i want to remove object which have same id (duplicated data) using javascript.
below is the input array
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
so as you see from above array there are duplicating data with id '1' and '2'.
if there is similar id i want include only one
so the expected output is like below,
const output = [
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
]
how can i do this. could someone help me with this. i am new to programming thanks.
You can use reduce to filter data from the array based on some condition like bellow
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
const result = input.reduce((accumulator, current) => {
let exists = accumulator.find(item => {
return item.id === current.id;
});
if(!exists) {
accumulator = accumulator.concat(current);
}
return accumulator;
}, []);
console.log(result);
Similar to this answer. You will have to change the const to let while declaring input though, or use a new variable I suppose.
filtered_input = input.filter((value, index, self) =>
index === self.findIndex((t) => (
t.id === value.id
))
)
There is a lot of good approachs here.
Here is my approach for removing matching property from the original array and sending it back in the return if found.
I prefer to use this one, if you are looping through a external array and matching them, this way you dont need to loop through the whole array again and again for each, because while you are finding the matches it keeps removing them from the original array, increasing performance.
Note that this will return the first match found
let id = "601985b485d9281d64056953"
let contacts = [{
...,
parent: "601985b485d9281d64056953",
...,
},
{
...,
parent: "601985b485d9281d64065128",
...,
}
]
function findAndRemoveObjectFromArray(array, internalProperty, externalProperty, convertType = "string", returnObject = false) {
let objIndex = -1
if (convertType === "string") objIndex = array.findIndex((obj) => String(obj[`${internalProperty}`]) === String(externalProperty));
if (convertType === "number") objIndex = array.findIndex((obj) => Number(obj[`${internalProperty}`]) === Number(externalProperty));
if (objIndex > -1) {
const object = array.splice(objIndex, 1);
if (returnObject) return object.shift()
return object
}
return [];
}
let currentContact = findAndRemoveObjectFromArray(contacts, "parent", id, 'string', true)
// Results:{..., parent: "601985b485d9281d64056953",...}
you could use Set to get rid of the duplicate data like this
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
]
const result = [...new Set(input.map(JSON.stringify))].map(JSON.parse)
console.log(result)
Below is another approach
const input = [
{
id: '1',
name: 'first',
},
{
id: '1',
name: 'first',
},
{
id: '2',
name: 'second',
},
{
id: '2',
name: 'second',
},
];
const uniqueIds = new Set();
const uniqueList = input.filter(element => {
const isDuplicate = uniqueIds.has(element.id);
uniqueIds.add(element.id);
return !isDuplicate;
});
console.log(uniqueList);
I am trying to return the objects which has key of submittedDate. But if i am trying with find() It's returning only the first object. And for map it's returning undefined for object not having submittedDate key. Please find my code with data and also the result I want. thanks in advance.
const data = [
{
id: '1',
name: 'Tully Stark',
submittedData:'mmmmm'
},
{
id:'2',
name: 'Nalani Romanova',
},
{
id:'3',
name: 'Nalani Romanova',
submittedData:'mmmmm'
}
]
const submitDate = data.find(item => item.submittedData)
console.log(submitDate)
data to return
const returnData = [
{
id: '1',
name: 'Tully Stark',
submittedData:'mmmmm'
},
{
id:'3',
name: 'Nalani Romanova',
submittedData:'mmmmm'
}
]
the .find by definition only returns the first matching object.
Array.prototype.find()
The find() method returns the value of the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned.
You need to use .filter
const submitDate = data.filter(item => item.submittedData)
const data = [{
id: '1',
name: 'Tully Stark',
submittedData: 'mmmmm'
},
{
id: '2',
name: 'Nalani Romanova',
},
{
id: '3',
name: 'Nalani Romanova',
submittedData: 'mmmmm'
}
]
const submitDate = data.filter(item => item.submittedData)
console.log(submitDate)
You can use Array.filter(), this will return all matching items.
const data = [ { id: '1', name: 'Tully Stark', submittedData:'mmmmm' }, { id:'2', name: 'Nalani Romanova', }, { id:'3', name: 'Nalani Romanova', submittedData:'mmmmm' } ]
const submitDate = data.filter(item => item.submittedData)
console.log(submitDate)
.as-console-wrapper { max-height: 100% !important; top: 0; }
For an object of this structure:
const myObj = {
id: 1,
name: '1',
children: [
{
id: 2,
name: '2',
children: [
{
id: 3,
name: '3',
children: []
}
]
},
{
id: 4,
name: '4',
children: [
{
id: 5,
name: '5',
children: [
{
id: 6,
name: '6',
children: [
{
id: 7,
name: '7',
children: []
}
]
}
]
}
]
},
]
}
How would I get an object by value (id)? So I'm looking for a function where if I call this:
findObj(myObj, 6);
It would return this:
{
id: 6,
name: '6',
children: [
{
id: 7,
name: '7',
children: []
}
]
}
Another example:
findObj(myObj, 3);
Would return this:
{
id: 3,
name: '3',
children: []
}
I know I need a recursion function. Heres what I have so far:
findObj(obj, id) {
if (obj.id === id) {
return obj;
}
obj.forEach(x => {
if (x.id === id) {
return x;
} else {
this.findObj(x.children, id);
}
});
}
(This is in an angular class)
At first sight I see some problems.
If you already have the ob.id === id inside the function, you don't need to double check for it later. Also, if findObj is a function defined in the scope like any other variable and is not in the "class" definition, you don't need to call it through this, the same way the first call to the findObj you do it without the this keyword.
Also, at first you pass an object to your method, but then you pass an object array (the obj.children), and also you check for the id inside a forEach method, where you pass a function (the x => { ... thingy), so when you return, you return from that function instead of the main function.
I've fixed it for you. I recommend you to understand what is happening and learn from it, as this will not happen if you know what you are doing (debug is your master here).
findObj(obj, id) {
if (obj.id === id) {
return obj;
}
for (var i = 0; i < obj.children.length; i++) { // No forEach, so when we return, we actually return from findObj
var r = findObj(obj.children[i], id); // We see if we have any return and let the "check logic" be defined on one location instead of duplicated.
if (r) {
return r;
}
}
}
You could check the object or check the children.
function find(object, id) {
var result;
if (object.id === id) return object;
object.children.some(o => result = find(o, id));
return result;
}
const object = { id: 1, name: '1', children: [{ id: 2, name: '2', children: [{ id: 3, name: '3', children: [] }] }, { id: 4, name: '4', children: [{ id: 5, name: '5', children: [{ id: 6, name: '6', children: [{ id: 7, name: '7', children: [] }] }] }] }] };
console.log(find(object, 5));
console.log(find(object, 6));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Two issues:
your return x; statement only returns from the forEach callback, not from the findObj function. Don't use forEach! A simple for … of loop will do
if your recursive call find the object and returns it, you ignore it and just continue iterating. Check whether you got a result and handle it appropriately.
I guess you're not looking for a full solution, so I leave that as an exercise :-)
I have a big problem. I want to create a function that remove equal 'parts' between two JSON files, with the output of function having the same structure, but without the 'equal parts'.
An example i have a JSON version of a DOM tree and i want keep only the difference between pages (remove nav footer ...)
Example
const a = {
id: '1',
child: [
{
id: '2',
child: [
{
id: '1'
},
{
id: '2'
}
]
},
{
id: '3',
child: [
{
id: '1'
},
{
id: '5'
}
]
}
]
}
And
const b = {
id: '1',
child: [
{
id: '2',
child: [
{
id: '1'
},
{
id: '4'
}
]
},
{
id: '3',
child: [
{
id: '1'
},
{
id: '4'
}
]
}
]
}
With a function
diff(a, b)
This result
{
id: '1',
child: [
{
id: '2',
child: [
{
id: '2'
}
]
},
{
id: '3',
child: [
{
id: '5'
}
]
}
]
}
I created this based on recursive function
const diff = (a, b) => {
if (Array.isArray(a)) {
}
if (typeof a === 'object') {
// ...
extract(a.child, b.child);
}
}
How do I do this? Is there an npm package? or with JSON Path? I want to create a function that remove the equal 'parts' between two JSON files with the output of the function having the same structure, but without the 'equal parts'.
I assume you can't guarantee the order of the id/value pairs?
I would suggest that you first recursively merge each layer, then go through and remove duplicates.
Edited With Code from the Recursion function
let c = [] // merged structure
for (var i=0; i<a.length; i++)
{
for (let j=0; j<b.length; j++)
{
if (a[i].id === j[i].id) {
c[i] = { id: a[i].id, child: a[i].child.concat(b[i].child) }
// next, sort the c[i].child, and
// loop through c[i].child and recur over any cases where
// c[i].child[k].id === c[i].child[k+1].id
// at the end, go back up the chain removing any structs where the
// id is a duplicate and has no children left
}
}
}
jsFiddle: http://jsfiddle.net/wenbert/W2qLz/2/
Even though I have provided the "initial data" for the selected_skill array, the $data becomes the first item in the select box.
var initialData = [
{
id: '1',
name: "Batman",
isDelete: false,
selected_skill: { <--- This part right here.
id: '2',
name: "Boxing",
isDeleted: false
},
skills: [
{
id: '1',
name: "Karate",
isDeleted: false},
{
id: '2',
name: "Boxing",
isDeleted: false
},
{
id: '6',
name: "Sonar",
isDeleted: false}
]},
{
id: '2',
name: "Hulk",
isDelete: false,
skills: [
{
id: '3',
name: "MMA",
isDeleted: false},
{
id: '4',
name: "Rage",
isDeleted: false},
{
id: '5',
name: "Extra Strength",
isDeleted: false}
]},
];
See the $data part in the screenshot below
I have the initial_data provided but when everything is "loaded", $data is automatically updated based on the first option for the select box.
How do I set the "selected option" this way?
In the screenshot, the selected_skill should have been:
selected_skill: {
id: '2',
name: "Boxing",
isDeleted: false
}
jsFiddle: http://jsfiddle.net/wenbert/W2qLz/2/
UPDATE:
The initialData in my real app is loaded using $.getJSON(). I do it with something like this:
$.getJSON(appUrl+"/getstuff/hero.json",
function(data){
ko.applyBindings(new Hero(data));
}
);
I can see that the result from the Firebug Console says that it is "Boxing" - I get Object { id="2", nameL: "Boxing", isDelete: false }. But then when everything has been rendered, the selected_skill is becomes the first option.
I hope this is making sense. If not, I would be glad to answer clarifications through the comments.
FINAL UPDATE
I used:
return item.id() === data.selected_skill.id
instead of
return data.selected_skill && skill.id === data.selected_skill.id;
then it worked.
I have marked the correct answer.
The issue is that the selected_skill object is a different object that the one in skills array rather than a reference to the same object.
In JavaScript,
var a = { name: "Bob" };
var b = { name: "Bob" };
var c = a;
alert(a === b); //false - different objects
alert(a === c); //true - reference to the same object
You would need to run some logic to match the selected object with one from the list. Maybe something like: http://jsfiddle.net/rniemeyer/W2qLz/3/