convert specific properties of object to an array of objects - javascript

This is my original Object:
Data = {
aesthetic: {
heritage: 'aesthetic',
description: 'sdokjosk',
value: 5
},
architectural: {
heritage: 'architectural',
description: 'doodsjdj',
value: 1
},
historical: {
heritage: 'historical',
description: 'dcnsdlnckdjsncksdjbk kjdsbcjisdc hsdk chjsd cjhds ',
value: 4
},
score: 3
};
i want to write a function that goes through the object and converts the properties only with 'heritage' 'description' and 'value' into an array that would look like this:
[{
"heritage": "aesthetic",
"description": "sdokjosk",
"value": 5
},
{
"heritage": "architectural",
"description": "doodsjdj",
"value": 1
},
{
"heritage": "historical",
"description": "dcnsdlnckdjsncksdjbk kjdsbcjisdc hsdk chjsd cjhds ",
"value": 4
}
]
This is what I have tried:
Object.values(Data)
but this returns an array with the 3 from the score property at the end

You can use Object.values() method to get the array of values, then filter only objects from it using Array#filter() method.
This is how should be your code:
var result = Object.values(Data).filter(x => typeof x == 'object');
Demo:
This is a working demo snippet:
var Data = {
aesthetic: {
heritage: 'aesthetic',
description: 'sdokjosk',
value: 5
},
architectural: {
heritage: 'architectural',
description: 'doodsjdj',
value: 1
},
historical: {
heritage: 'historical',
description: 'dcnsdlnckdjsncksdjbk kjdsbcjisdc hsdk chjsd cjhds ',
value: 4
},
score: 3
};
var result = Object.values(Data).filter(x => typeof x == 'object');
console.log(result);

If you want to check all the keys you mentioned should present you can go with this :
Object.values(Data).filter(function(data){return data["heritage"] && data["description"] && data["value"]})

Related

Get cumulative length of array inside array of objects

I have been searching for quite a while but cannot find an answer to my issue. The problem is pretty simple; I have an array of objects, each containing another array of objects. I want to get the cumulative length of all arrays inside all objects.
Here is some sample data:
const items = [
{
id: 1,
title: "Test 1",
data: [
{
...
},
{
...
},
]
},
{
id: 2,
title: "Test 2",
data: [
{
...
},
]
}
]
In this sample, the length should be 3 since there is 2 objects inside the first object's data property and 1 object inside the second object's data property.
pretty simple
const items =
[ { id: 1, title: "Test 1", data: [{a:1},{a:1} ] }
, { id: 2, title: "Test 2", data: [{a:1},{a:1},{a:1},{a:1}] }
]
console.log('cumulative length ', items.reduce((a,c)=>a+c.data.length,0) )
All you need to do is loop through all items you got, check the length of the data array of each item and add that length to a variable. Here is a working snippet:
const items = [
{
id: 1,
title: "Test 1",
data: [
{
},
{
},
]
},
{
id: 2,
title: "Test 2",
data: [
{
},
]
}
];
// Initialize the count variable as 0
var count = 0;
// Pass through each item
items.forEach((item)=>{
// Adding the count of data of each item
count += item.data.length;
});
// Outputting the count
console.log(count);
If you want to use for of loop that works too.
const countObjects = (arrayInput) => {
let totalCount = 0
for(let item of items) {
totalCount += item.data.length
}
return totalCount
}
console.log(countObjects(items))

How to access object property by variable in Javascript [duplicate]

This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 3 years ago.
I have an object like
let arr = [
{
title: "hello",
pivot: {
id: 1,
bid: 3
}
},
{
title: "home",
pivot: {
id: 2,
bid: 3
}
},
{
title: "nice",
pivot: {
id: 3,
bid: 3
}
}
];
I want to access its property dynamically. I want to access id property's value from pivot from first object of this array. And it's should be dynamic.
This is what I tried already.
let s = "0.pivot.id"
let res = arr[s]
console.log(res)
I can access by arr[0].pivot.id but this is not my case. I want it dynamically.
You can split the string and loop through it updating a variable refrencing the last found value :
let arr = [
{
title: "hello",
pivot: {
id: 1,
bid: 3
}
},
{
title: "home",
pivot: {
id: 2,
bid: 3
}
},
{
title: "nice",
pivot: {
id: 3,
bid: 3
}
}
];
let s = "0.pivot.id";
const getValue = (arr, str) => {
let ref = arr;
const keys = str.split(".");
keys.forEach(k => {
ref = ref[k];
});
return ref;
};
const result = getValue(arr, s);
console.log(result);
what you tried would give you a property which key was 0.pivot.id. So it might work if your object looks like this
{
'0.pivot.id': 'something'
}
There is no native way to access deeper level of an object dynamically. You would need to use recursion for that.
It's quite easy though, You could simply split your key into an array of keys and then recursively check your array for matching keys.
let arr = [
{
title: "hello",
pivot: {
id: 1,
bid: 3
}
},
{
title: "home",
pivot: {
id: 2,
bid: 3
}
},
{
title: "nice",
pivot: {
id: 3,
bid: 3
}
}
];
function getDynamicKeyRecursively(object, key) {
// the key needs to be an array,
// if it isn't, we split it into an array
if(typeof key === 'string') {
key = key.split('.');
}
// we get the current value of the current object
let currentValue = object[key[0]];
// remove the first index of the key
key.shift()
// if the current value is an object or an array, we recursively check this value for what we want
// otherwise, we return the value.
return Array.isArray(currentValue) || typeof currentValue === 'object' ? getDynamicKeyRecursively(currentValue, key) : currentValue;
}
console.log(getDynamicKeyRecursively(arr, '1.pivot.id'));

How to sum a specific option in an array of objects?

I have this array:
[
{ id: "1", option { points: "1"} },
{ id: "2", option { points: "20"} },
{ id: "3", option { points: "4"} },
]
I'm trying to sum all the objectoption that have as property points, so I did:
var total_points = this.my_arr.reduce(function(a, b){
return a + b.option.points;
}, 0);
but this return a concatenation of the index of each id, something like: 012, that is of course wrong.
The expected output is: 25
You must convert your strings to numbers, for example:
var total_points = this.my_arr.reduce(function(a, b){
return a + parseInt(b.option.points);
}, 0);
Correct your object and cast the b as Number. In the object the values are strings so when + is used with string concatenations happens not addition. That's why the strings are converted to numbers and then added
var e=[
{ id: "1", option :{ points: "1"} },
{ id: "2", option :{ points: "20"} },
{ id: "3", option :{ points: "4"} },
]
var total_points = e.reduce(function(a, b){
return a + Number(b.option.points);
}, 0);
console.log(total_points);
In your object options is string when you use + operator b/w two strings it joins both of then. Use you convert string to number using parseInt() or Number()
var total_points = this.my_arr.reduce(function(a, b){
return a + parseInt(b.option.points);
}, 0);
You must convert the string to a number, you can use parseInt for that, or even simpler prepend a + before the string.
This version works with NaN, undefined or missing properties:
const data = [
{ id: "1", option: { points: "1" } },
{ id: "2", option: { points: "20" } },
{ id: "3", option: { points: "4" } },
{ id: "4", option: { points: NaN } },
{ id: "5", option: { points: undefined } },
{ id: "6", option: { } },
{ id: "7" },
];
const totalPoints = data.reduce((accum, elem) => {
const value = elem.option && elem.option.points ? +elem.option.points : 0;
return accum + value;
}, 0);
console.log(totalPoints);

Lodash - DifferenceBy with different identity

I have the following array:
[
{
id: 1
},
{
id: 2
},
{
id: 3
},
{
id: 4
}
]
Every 5 seconds my application receives a new array and I need to compare the difference between the next one...
So the next array is:
[
{
conversation_id: 1
},
{
conversation_id: 2
},
{
conversation_id: 4
}
]
Considering that identity is different. How can I compare with the previous and get an array with the excluded item?
[
{
id: 3
}
]
Use _.differenceWith():
const prev = [{"id":1},{"id":2},{"id":3},{"id":4}]
const next = [{"conversation_id":1},{"conversation_id":2},{"conversation_id":4}]
const diff = _.differenceWith(prev, next, ({ id }, { conversation_id }) => _.eq(id, conversation_id))
console.log(diff)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>
I think you can use mix of javascript and lodash to solve this problem.
var arrayList = [
{
id: 1
},
{
id: 2
},
{
id: 3
},
{
id: 4
}
];
var conv_array = [
{
conversation_id: 1
},
{
conversation_id: 2
},
{
conversation_id: 4
}
];
var itemsNotInArray = [];
arrayList.filter(function (item) {
if (!_.find(conv_array, {conversation_id: item.id })) {
console.log("not in array", item);
itemsNotInArray.push(item);
}
});
console.log("result you expected", itemsNotInArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Filter the first array and compare each value till you find a missing id :
var array1 = [{
id: 1
},
{
id: 2
},
{
id: 3
},
{
id: 4
}
];
var array2 = [{
conversation_id: 1
},
{
conversation_id: 2
},
{
conversation_id: 4
}
];
var test = array1.filter(
conv => !array2.find(
id => id.conversation_id === conv.id
)
);
console.log(test)
From lodash documentation, the third argument to differenceBy is
[iteratee=_.identity] (Function): The iteratee invoked per element.
Based on this, you can use
var current = [
{
id: 1
},
{
id: 2
},
{
id: 3
},
{
id: 4
}
];
and
var next = [
{
conversation_id: 1
},
{
conversation_id: 2
},
{
conversation_id: 4
}
];
then
var difference = _.differenceBy(current, next, function(obj) {
return obj.id || obj.conversation_id;
});
Or shortened with an arrow function:
var difference = _.differenceBy(current, next, (x) => x.id || x.conversation_id)

Get all the objects from state which is having multiple arrays

Actually I have a state data which is an object , It has following structutre,
{ one : [ { abc:1 }, { abc: 2 }], two : [ { abc:3 }, { abc: 4 }, three : [ { abc:5 }, { abc: 6 }]] }
So its like an arry of objects in an state object .
Now, I want to create an array of objects which will have all these objects .
So I want to have it like,
[{ abc:1 }, { abc: 2 },{ abc:3 }, { abc: 4 },{ abc:5 }, { abc: 6 }]
The way I tried is using for loop.
let quizCriteriaObj = [];
let low = this.props.lowQuizData["Low"];
let High = this.props.lowQuizData["High"];
let Medium = this.props.lowQuizData["Medium"];
console.log("data is ", low);
for (let i = 0; i <= low.length - 1; i++) {
quizCriteriaObj.push(low[i]);
}
for (let i = 0; i <= High.length - 1; i++) {
quizCriteriaObj.push(High[i]);
}
for (let i = 0; i <= Medium.length - 1; i++) {
quizCriteriaObj.push(Medium[i]);
}
console.log(quizCriteriaObj);
I have taken each field aside from that object and using a for loop on every field. SO, It is working for me. But , I think this is not a proper solution for me .Is there any thing That I am doing wrong ?
Modern javascript makes this trivial
Array.prototype.flat
Please note: Array.prototype.flat is a stage 3 TC39 proposal, so is not part of the ECMAScript specification (yet)
It is supported in all modern browsers (and can be polyfilled for Microsofts attempts at browsers, both Internet Explorer and Edgey)
Note: I assume you mistyped the "source" object, because as it was, it was invalid
let obj = {
one : [
{ abc:1 },
{ abc: 2 }
],
two : [
{ abc:3 },
{ abc: 4 }
],
three : [
{ abc:5 },
{ abc: 6 }
]
}
let ftw = Object.values(obj).flat(); //<== single line of code is all you need
console.log(JSON.stringify(ftw))
You can use Object.values to convert the object into an array. Use spread syntax and concat() to flatten the array
var obj ={"one":[{"abc":1},{"abc":2}],"two":[{"abc":3},{"abc":4}],"three":[{"abc":5},{"abc":6}]}
var result = [].concat(...Object.values(obj));
console.log(result);
You can use a for...in loop
let obj = { one : [ { abc:1 }, { abc: 2 }], two : [ { abc:3 }, { abc: 4 }], three : [ { abc:5 }, { abc: 6 }] };
let result = [];
for (let key in obj) result = [...result, ...obj[key]];
console.log(result);
Using lodash is simple:
const obj = { one : [ { abc:1 }, { abc: 2 }], two : [ { abc:3 }, { abc: 4 }, three : [ { abc:5 }, { abc: 6 }]] }
_.flatten(obj)
// return => [{ abc:1 }, { abc: 2 },{ abc:3 }, { abc: 4 },{ abc:5 }, { abc: 6 }]
Good question you can't simply spread the arrays so a good one liner
for this would be.
state = {
one : [ { abc:1 }, { abc: 2 }],
two : [ { abc:3 }, { abc: 4 }],
three : [ { abc:5 }, { abc: 6 }]
}
var result = Object.values(state).flat() // solution
console.log(result)

Categories

Resources