I am getting my head around lodash for js and trying to select the object property with the name 'one' from this object by using the id key:
{
"one": {
"id":"peter",
"somevalue":1
},
"two": {
"id":"john",
"somevalue":1
}
}
So as a result I would like:
{
"id":"peter",
"somevalue":1
}
Sorry I updated the question:
How can I accomplish this with lodash returning this result based on the name in this case 'one' by using the key , id='peter'?
With Lodash (#1):
const value = _.find(obj, prop => prop.id === 'peter');
With Lodash (#2):
const value = _.find(obj, {id: 'peter'});
With Lodash (#3): (credit to hughes)
const value = _.find(obj, 'id', 'peter');
Plain JS:
const key = Object.keys(obj).find(key => obj[key].id === 'peter');
const value obj[key];
Future JS:
const value = Object.values(obj).find(prop => prop.id === 'peter');
More documentation on filter here: https://lodash.com/docs#filter
var obj = {
"one": {
"id":"peter",
"somevalue":1
},
"two": {
"id":"john",
"somevalue":1
}
};
console.log(_.filter(obj, {id:"peter"}));
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
Related
I have an Array of objects and one object
const filterArray = [{bestTimeToVisit: 'Before 10am'}, {bestDayToVisit: Monday}]
This values are setting in a reducer and the payload will be like
{bestTimeToVisit: 'After 10am'}
or
{bestDayToVisit: Tuesday}.
So what I need is when I get a payload {bestTimeToVisit: 'After 10am'} and if bestTimeToVisit not in filterList array, then add this value to the filterList array.
And if bestTimeToVisit already in the array with different value, then replace the value of that object with same key
if(filterArray.hasOwnProperty("bestTimeToVisit")) {
filterArray["bestTimeToVisit"] = payload["bestTimeToVisit"];
} else {
filterArray.push({"bestTimeToVisit": payload["bestTimeToVisit"]});
}
I convert the object array into a regular object and then back into an object array. makes things less complicated. I'm making the assumption each object coming back only has one key/value and that order doesnt matter.
const objectArraytoObject = (arr) =>
arr.reduce((acc, item) => {
const key = [Object.keys(item)[0]];
return { ...acc, [key]: item[key] };
}, {});
const newValues = [{ someKey: 'something' }, { bestDayToVisit: 'Tuesday' }];
const filterArray = [
{ bestTimeToVisit: 'Before 10am' },
{ bestDayToVisit: 'Monday' },
];
const newValuesObj = objectArraytoObject(newValues);
const filterObj = objectArraytoObject(filterArray);
const combined = { ...filterObj, ...newValuesObj };
const combinedToArray = Object.keys(combined).map((key) => ({
[key]: combined[key],
}));
console.log(combinedToArray);
Need to iterate over the array and find objects that satisfy for modification or addition if none are found.
function checkReduced(filterrray,valueToCheck="After 10am"){
let isNotFound =true;
for(let timeItem of filterrray) {
if(timeItem.bestTimeToVisit && timeItem.bestTimeToVisit !== valueToCheck) {
timeItem.bestTimeToVisit=valueToCheck;
isNotFound=false;
break;
}
}
if(isNotFound){filterrray.push({bestTimeToVisit:valueToCheck})}
}
const filterArray = [{bestDayToVisit: "Monday"}];
checkReduced(filterArray,"After 9am");//calling the function
const updateOrAdd = (arr, newItem) => {
// get the new item key
const newItemKey = Object.keys(newItem)[0];
// get the object have the same key
const find = arr.find(item => Object.keys(item).includes(newItemKey));
if(find) { // the find object is a reference type
find[newItemKey] = newItem[newItemKey]; // update the value
} else {
arr.push(newItem); // push new item if there is no object have the same key
}
return arr;
}
// tests
updateOrAdd([{ a: 1 }], { b: 2 }) // => [{ a: 1 }, { b: 2 }]
updateOrAdd([{ a: 1 }], { a: 2 }) // => [{ a: 2 }]
I receive an object that looks like this:
this.tokensData = {
O: {
id: 0,
name: value1,
organization: organization1,
...,
},
1: {
id: 1,
name: value1,
organization: organization1,
...,
},
2: {
id: 2,
name: value2,
organization: organization2,
...,
},
...
}
I want to filter by id and remove the Object which id matches the id I receive from the store. What I tried so far:
const filteredObject = Object.keys(this.tokensData).map((token) => {
if (this.$store.state.id !== this.tokensData[token].id) {
return this.tokensData[token];
}
});
This replaces the Object with undefined - which would work for my purposes but is obviously not ideal.
Any help is much appreciated!
Try to use Object.entries and then Object.fromEntries() to create an object from a list of key-value pairs:
let store = [0 , 1];
const result = Object.entries(tokensData).filter(([k, v]) => !store.some(s => s == v.id));
console.log(Object.fromEntries(result));
An example:
let tokensData = {
O: {
id: 0,
name: '',
organization: '',
},
1: {
id: 1,
name: '',
organization: '',
},
2: {
id: 2,
name: '',
organization: '',
}
}
let store = [0 , 1];
const result = Object.entries(tokensData).filter(([k, v]) => !store.some(s => s == v.id));
console.log(Object.fromEntries(result));
You can do this by using Object.entries and Object.fromEntries:
const filteredObject = Object.fromEntries(
Object.entries(this.tokensData).filter(
([key, value]) => value.id !== this.$store.state.id
)
)
This can be done by cloning the object and removing the object at the ID:
const removeObjectByID = (obj, id) => {
// first create a copy of the object
const copy = JSON.parse(JSON.stringify(obj))
// next, delete the one entry you don't want
delete copy[id]
// finally, return the new object
return copy
}
// Test
const data = {a:1, b: 2, c: 3}
console.log(removeObjectByID(data, 'b')) // { a: 1, c: 3 }
The problem with undefined is caused by using this in your arrow function. Javascript scoping gives a different meaning to this if the function is a arrow function.
Furthermore I suggest to use filter.
.map is used to transform A -> B.
.filter should be used to filter out objects.
Now if we combine that this would become something like this.
function filterById(token) {
return this.$store.state.id !== this.tokensData[token].id;
}
function getTokenData(token) {
return this.tokensData[token]
}
const token = Object.keys(this.tokensData)
.filter(filterById)
.map(getTokenData);
});
Please note that I'm not using arrow functions. Arrow function can't refer to this due to the way javascript handles scoping.
An alternative approach could be to reference this into a variable, so your arrow function can access the variable.
const self = this;
const token = Object.keys(this.tokensData)
.filter(token => self.$store.state.id !== self.tokensData[token].id)
.map(token => self.tokensData[token]);
Too make it even nicer you could utilize Object.entries. This will return an array of key and value, which you can destructure using es6 syntax as following [key, value].
const self = this;
const token = Object.entries(this.tokensData)
.filter(([key, value]) => self.$store.state.id !== value.id)
.map(([key, value]) => value);
I have a collection which looks like this:
var array = [
{ 'key1': 'val1'},
{ 'key2': 'val2'}
];
I want a function which takes array and value as parameters and returns key of that value (values are unique)
getKey(array, 'val1');
>>>>> output: 'key1'
I tried the following solution but it says key property is not defined:
getKey(array, value) {
var keys = [];
array.forEach(function(element) {
for (key in element) {
if(value == element[key]) {
keys.push(key);
}
}
})
return keys[0];
},
var arr = [{ 'key1': 'val1'}, { 'key2': 'val2'}];
function getKey(data,value) {
let keys=[];
data.forEach(function(element) {
for (key in element) {
if(element[key]==value)
keys.push(key);
}
});
return keys
}
console.log(getKey(arr, 'val1'))
Create an inverse object with value as key and key as value. And then finally access the value from object as key.
var array = [{ 'key1': 'val1'},{ 'key2': 'val2'}];
function getKey(arr, val) {
let obj = arr.reduce((a,c) => {
Object.entries(c).forEach(([k,v]) => a[v]=k);
return a;
}, {})
return obj[val];
}
console.log(getKey(array, 'val1'));
In pure JS you can take all the entries, flatten them and simply search the value in all couples and if found then just take the first entry of that couple.
[].concat(...array.map(Object.entries)).find(a=>a[1]=='val1')[0]
Here is an working example:
var array = [{'key1': 'val1'}, {'key2': 'val2'}, {'key3': 'val3'}],
getKey = (arr,v)=>[].concat(...arr.map(Object.entries)).find(a=>a[1]==v)[0];
console.log(getKey(array, 'val2'));
console.log(getKey(array, 'val3'));
However, I will suggest you to use lodash (or underscore, or lazy) to make it more cleaner and simple.
Here is a lodash approach:
_.findKey(_.merge({}, ...array), s=>s=='val1')
Here is a woking example:
var array = [{'key1': 'val1'}, {'key2': 'val2'}, {'key3': 'val3'}],
getKey = (arr,v)=>_.findKey(_.merge({}, ...arr), s=>s==v);
console.log(getKey(array, 'val2'));
console.log(getKey(array, 'val3'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
You can also try this:
var arr = [{ 'key1': 'val1'}, { 'key2': 'val2'}];
function getKey(arr, val) {
var result = 'not found';
arr.forEach(obj => {
for (var key in obj) {
if(obj[key] === val) result = key;
}
});
return result;
}
console.log(getKey(arr, 'val1'));
console.log(getKey(arr, 'value'));
At present, I do this approach:
var obj = {
sender: {
name: "tech"
}
}
var str = "sender.name".split('.');
console.log( obj[str[0]][str[1]] ); //getting update as 'Tech'
In the above I use obj[str[0]][str[1]] for just 2 step, this is works fine. In case if I received a long node parent and child this approach not going to work.
Instead is there any correct dynamic way to do this?
You can use array#reduce to navigate through each key.
var obj = { sender: { name: "tech" } };
var str = "sender.name".split('.').reduce((r,k) => r[k],obj);
console.log(str);
You can use reduce:
var obj = {
foo: {
bar: {
baz: {
sender: {
name: "tech"
}
}
}
}
}
const props = "foo.bar.baz.sender.name".split('.');
const val = props.reduce((currObj, prop) => currObj[prop], obj);
console.log(val);
You could split the string and reduce the path for the result. The function uses a default object for missing or not given properties.
function getValue(object, path) {
return path
.split('.')
.reduce(function (o, k) { return (o || {})[k]; }, object);
}
var obj = { sender: { name: "tech" } },
str = "sender.name";
console.log(getValue(obj, str));
You should be looking into libraries such as "https://lodash.com/"
https://lodash.com/docs/4.17.10
Use _.get : https://lodash.com/docs/4.17.10#get
You can simply write _.get(obj, 'sender.name', 'default') and you will get the value as you expect
I'm fetching json data with ajax. Then I want to output it in Griddle using griddle-react. The problem is I cannot convert my array to a Griddle readable array.
After the ajax fetch i made a callback function:
function convert(obj) {
console.log(obj);
Object.keys(obj).forEach(function (key) {
let format = JSON.stringify(obj[key]);
console.log(format);
self.setState(() => ({ data: key[format] }));
});
}
The first console.log output looks like this:
{
{
"BTC": {
"opening_price": "9845000",
"closing_price": "9967000",
"min_price": "9814000",
"max_price": "10047000",
"average_price": "9928071.5654",
"units_traded": "7242.04659594",
"volume_1day": "7242.04659594",
"volume_7day": "73491.92898643",
"buy_price": "9967000",
"sell_price": "9968000"
},
}
}
My functions makes it look like this: (second console.log):
{
"opening_price": "9846000",
"closing_price": "9965000",
"min_price": "9814000",
"max_price": "10047000",
"average_price": "9929422.0905",
"units_traded": "7200.46713802",
"volume_1day": "7200.467F13802",
"volume_7day": "73395.33311647",
"buy_price": "9959000",
"sell_price": "9964000"
}
I want it to convert to the following array, basically adding the name item, and thereafter Griddle can read it:
{
"name": "BTC",
"opening_price": "9845000",
"closing_price": "9967000",
"min_price": "9814000",
"max_price": "10047000",
"average_price": "9928071.5654",
"units_traded": "7242.04659594",
"volume_1day": "7242.04659594",
"volume_7day": "73491.92898643",
"buy_price": "9967000",
"sell_price": "9968000"
},
What I'm doing wrong here? I'm sure its pretty close to what I want, but I can't figure it out at this point.
You can use Object.entries to get the keys and values. Use Object.assign to make new objects
var obj = {
"BTC": {"opening_price": "9845000","closing_price": "9967000","min_price": "9814000","max_price": "10047000","average_price": "9928071.5654","units_traded": "7242.04659594","volume_1day": "7242.04659594","volume_7day": "73491.92898643","buy_price": "9967000","sell_price": "9968000"}
}
var newObj = Object.entries(obj).reduce((c, [i, v]) => Object.assign(c, {name: i}, v), {});
console.log(newObj);
If you have several keys, you can use map
var obj = {
"BTC": {"opening_price": "9845000","closing_price": "9967000","min_price": "9814000","max_price": "10047000","average_price": "9928071.5654","units_traded": "7242.04659594","volume_1day": "7242.04659594","volume_7day": "73491.92898643","buy_price": "9967000","sell_price": "9968000"},
"OTH": {"opening_price": "9845000","closing_price": "9967000","min_price": "9814000","max_price": "10047000","average_price": "9928071.5654","units_traded": "7242.04659594","volume_1day": "7242.04659594","volume_7day": "73491.92898643","buy_price": "9967000","sell_price": "9968000"},
}
var newArr = Object.entries(obj).map(([i, v]) => Object.assign({}, {name: i}, v));
console.log(newArr);
Without including date property
var obj = {
"KNC": {"opening_price": "2731","closing_price": "2788","min_price": "2693","max_price": "2849","average_price": "2790.5368","units_traded": "3178032.25814499211673","volume_1day": "3178032.25814499211673","volume_7day": "110687333.315264505902311000","buy_price": "2783","sell_price": "2788"},
"date": "1525269153470"
}
var newObj = Object.entries(obj).reduce((c, [i, v]) => i !== 'date' ? Object.assign(c, {name: i}, v) : c, {});
console.log(newObj);
Can you update your function to have this line in it?
obj[key]["name"] = key
function convert(obj) {
console.log(obj);
Object.keys(obj).forEach(function (key) {
obj[key]["name"] = key;
let format = JSON.stringify(obj[key]);
console.log(format);
//self.setState(() => ({ bithumbData: key[format] }));
});
}
function convert(obj){
var parentKey = Object.keys(obj)[0];//Getting parent first element key
obj = obj[parentKey];
var newObj = {}; //Creating new empty jason object
newObj['name'] = parentKey; //key apply as name element to new jason object
for(var key in obj) //looping each child element
newObj[key] = obj[key]; //child applying to new jason object
return newObj;
}
console.log(JSON.stringify(convert(obj)));