Get key name of a javascript object in an array of objects - javascript

I have some Entries, those entries have a Category assigned to them, and each entry has a numeric Value;
{
category: "cat1",
value: -100
}
This is my entry ^. I run a Loadash GroupBy to group all the categories.
const groups = _.groupBy(dataSource, (entry) => entry.category);
This snippet here returns like this:
{
"cat1": [
{
category: "cat1",
value: -100
},
{
category: "cat1",
value: +10
},
],
"cat2": [
{
category: "cat2",
value: -100
},
{
category: "cat2",
value: +40
},
//and so on...
}
The keys are the Category names. The objects are the related entries.
I need to run a consecutive Map with an embedded Reduce to reduce the arrays to an integer through the sum of each entry's value.
const categoryValues = _.map(groups, (element) => {
return {
categoryName: ???????,
//*I DONT KNOW WHAT GOES HERE ^,
//I NEED THE NAME OF THE CATEGORY TO BE HERE*
categoryValue: _.reduce(element,(acc, el) => el.value,0),
};
});
Thats because my graph api needs his dataset array to be formed by objects like this one:
{
"categoryName": "cat1", //*THIS IS MISSING*
"categoryValue": 999
}
How can I access the key name of each array? I need to know how the category is named, so that the graph will display its name.
What needs to be written where I put my question marks?

You can get the name of the category from the second parameter of the callback function. This callback function is called by the lodash library and when it calls map function 3 arguments (value, key, collection). map
const categoryValues = _.map(groups, (element, name) => {
return {
categoryName: name, //I DONT KNOW WHAT GOES HERE, I NEED THE NAME OF THE CATEGORY TO BE HERE*
categoryValue: _.reduce(element, (acc, el) => el.value, 0),
};
});

The documentation for map says:
Creates an array of values by running each element in collection thru
iteratee. The iteratee is invoked with three arguments: (value,
index|key, collection).
As you can see, the second parameter passed to the iteratee is the original key in the collection. So, just add another parameter to the iteratee and use that:
const categoryValues = _.map(groups, (element, name) => {
return {
categoryName: name,
categoryValue: _.reduce(element,(acc, el) => el.value,0),
};
});

// this is the simple way.
var arr = {
iamkeysA : [1,2,3],
iamkeysB : [4,5,6]
}
var keys_ = Object.keys(arr); // now you get the list of keys name.
console.log( keys_[0] );
console.log( keys_[1] );

Related

how to update the array object using id and the props in javascript

I have an array object and I want to update the array object using id and props.
below is the structure of array object,
array object = [{columGrp:"All",deafultColumnName:"a",id:0},{columGrp:"ll",deafultColumnName:"ww",id:1},{columGrp:"oo",deafultColumnName:"qq",id:2},{columGrp:"qq",deafultColumnName:"ee",id:3}]
I have an editable table design and when a field changes I am passing field name, id, and changed value. based on that how can I update the object array.
const onChange=(props,value,id)=>{
//code here
}
onChange("columGrp","qwerty",1);
// result =>
array object = [{columGrp:"All",deafultColumnName:"a",id:0},{columGrp:"qwerty",deafultColumnName:"ww",id:1},{columGrp:"oo",deafultColumnName:"qq",id:2},{columGrp:"qq",deafultColumnName:"ee",id:3}]
a help would be really appreciable.
You can find the object by id from your array of objects using the filter function. If the object exists, you then change the given property, passing the given value. Objects work by reference in javascript so any changes in the found object will affect your object inside your array too.
const objectsArray = [{
columGrp: "All",
deafultColumnName: "a",
id: 0
}, {
columGrp: "ll",
deafultColumnName: "ww",
id: 1
}, {
columGrp: "oo",
deafultColumnName: "qq",
id: 2
}, {
columGrp: "qq",
deafultColumnName: "ee",
id: 3
}];
const onChange = (props, value, id) => {
const obj = objectsArray.find(x => x.id === id);
if (obj) {
obj[props] = value;
}
}
onChange("columGrp", "qwerty", 1);
console.log(objectsArray)

What is the best way to delete objects from Array

I am wondering if what is the best way to find all Indexes of objects in an Array and then delete them from the Array.
Currently, my code looks like as below;
var data = _.find(group.value, function(valueItem){ return valueItem.value == filter.value });
var index =_.indexOf(group.value,data);
group.value.splice(index,1);
This works great, but only gets me the first index if the index is more than once. So, I am looking for a method that will get me all indexes in my Array, so I can loop through in remove all
Use filter to create a new array of objects.
Based on your example this code creates new arrays based on the value (name) of each value property. I've wrapped the filter code in a function (getData) that you can call with the original array and the name you want to check as arguments.
If there is no match the function will return an empty array.
const arr = [
{ id: 1, value: 'bob' },
{ id: 2, value: 'dave' },
{ id: 3, value: 'bob' },
{ id: 4, value: 'bob' }
];
function getData(arr, name) {
return arr.filter(obj => obj.value === name);
}
console.log(getData(arr, 'bob'));
console.log(getData(arr, 'dave'));
console.log(getData(arr, 'mary'));

Alternative to eval for converting a string to an object

I have a function that is using eval to convert a string with an expression to an object based on the parameter.
let indexType = ["Mac", "User", "Line", "Mask", "Ip", "Location"]
const filterIndex = (item) => {
filteredIndexSearch = []
eval(`search${item}`).forEach((e) => filteredIndexSearch.push(searchData[e.key]))
}
filterIndex(indexType[searchTotal.indexOf(Math.max(...searchTotal))])
searchData is an array that returns values based on the user input.
searchTotal is an array with the length of each search{item} array.
The filterIndex function takes the highest value from the searchData array and corresponds it to the indexType array, then use eval to convert the string to an object to pass the value to the filteredIndexSearch array.
What would be a better alternative to eval?
EDIT
To add more information on what this does:
searchData = [
[
{
key: 1,
data: "0123456789101"
},
{
key: 1,
data: "John Smith"
}
],
[
{
key: 2,
data: "0123456789102"
},
{
key: 2,
data: "Jane Smith"
},
]
]
const search = (data, key, container) => {
if (!data) data = "";
if (data.toLowerCase().includes(string)) {
container = container[container.length] = {
key: key,
data: data
}
}
}
const returnSearch = () => {
for (let i = 0; i < searchData.length; i++) {
search(searchData[i][0].data, searchData[i][0].key, searchMac)
search(searchData[i][1].data, searchData[i][1].key, searchUser)
}
}
returnSearch()
The data is incomplete, but hopefully conveys what I'm trying to do.
search will take the user input, and store the information in the corresponding array. If I input "Jo", it will return the searchUser array with only the "John Smith" value and all the other values with the same key. Inputting "102" returns the searchMac with the "0123456789102" value and all other values with the same key.
At the end of the day. I just want to convert search${parameter} to an object without using eval.
Move your global arrays into an object.
Somewhere it appears that you're defining the arrays, something like:
searchMac = [...];
searchUser = [...];
...
Instead of defining them as individual arrays, I'd define them as properties in an object:
searchIndices.Mac = [...];
searchIndices.User = [...];
...
Then, instead of using eval, your can replace your eval().forEach with searchIndices[item].forEach.
If the order of your search isn't important, your can instead loop through the keys of searchIndices:
Object.keys(searchIndices).forEach(item => {
searchIndices[item].forEach(...);
});
This ensures that if you ever add or drop an entry in searchIndices, you won't miss it or accidentally error out on an undefined search index.
Any time you have a situation with variables named x0, x1 etc, that should be a red flag to tell you you should be using an array instead. Variable names should never be semantically meaningful - that is code should never rely on the name of a variable to determine how the code behaves. Convert search0 etc into an array of search terms. Then use:
const filterIndex = (item) => search[item].map(i => searchData[i.key]);
filteredIndexSearch = filterIndex(indexType[searchTotal.indexOf(Math.max(...searchTotal))]);
(simplifying your code). Note that in your code, filteredIndexSearch is modified inside the arrow function. Better to have it return the result as above.

Merging an array based on key and adding their values. Javascript/Es6/React

There are just 2 objects in an array where I need your attention at. I'm trying to find a way to merge these two objects into a single object based on item.Symbol and then add the values of their corresponding item.TotalCost, item.Price, and item.Quantity to the new object.
I tried doing a Set function but they just merge into 1 object and the values aren't added. I'm receiving an object like this:
[{
CompanyName: "Microsoft Corp."
Date: 1606503905
Price: 215.23
Quantity: 50
Symbol: "MSFT"
TotalCost: 10761.5
},
{
CompanyName: "Microsoft Corp."
Date: 1606503913
Price: 215.23
Quantity: 25
Symbol: "MSFT"
TotalCost: 5380.75
}
]
Here is my code so far:
let set = new Set()
const newSet = Objects.filter(item => {
if (!set.has(item.Symbol)) {
set.add(item.Symbol)
return true;
}
return false},set
)
console.log(newArray)
Note that the Objects variable contains the array of objects shown in the first code block.The set function I wrote only merges them into a single object based on their Symbol but I don't know where to go from here. I'm praying to the Javascript Overlords and Es6 Sith Lords to heed my call. May the force be with you.
Reduce the array of objects to an object, using the Symbol property as the key. If the key doesn't exist on the object, assign a clone of the current item to the key. If it exists, add the current item's values to the existing object:
const arr = [{"CompanyName":"Microsoft Corp.","Date":1606503905,"Price":215.23,"Quantity":50,"Symbol":"MSFT","TotalCost":10761.5},{"CompanyName":"Microsoft Corp.","Date":1606503913,"Price":215.23,"Quantity":25,"Symbol":"MSFT","TotalCost":5380.75}]
const newArray = Object.values(
arr.reduce((acc, o) => {
if(!acc[o.Symbol]) acc[o.Symbol] = { ...o }
else {
acc[o.Symbol].Price += o.Price
acc[o.Symbol].Quantity += o.Quantity
acc[o.Symbol].TotalCost += o.TotalCost
}
return acc
}, {})
);
console.log(newArray)

lodash sortBy then groupBy, is order maintained?

I'm having trouble figuring out from the lodash documentation if my assumption about sorting and grouping is correct.
If I use sortBy, then use groupBy, do the arrays produced by groupBy maintain the sort order of items?
For example, say I have the following array:
var testArray = [[5,6],[1,3],[5,4],[5,1]]
And I would like to group these by their first element, but also have them sorted by their second element within these groups. So, in lodash I assume I can do the following:
_.chain(testArray)
.sortBy(function (item) { return item[1]; })
.groupBy(function (item) { return item[0]; })
.value()
Which ends up producing what I would expect it to:
{
1: [[1,3]]
5: [[5,1],[5,4],[5,6]]
}
Is this just coincidence? Is there anything about how sortBy and groupBy work that ensures this ordering of the grouped arrays? The documentation says that sortBy is a stable sort, does that in the same way apply to groupBy? Is there any reason I should not assume this will work every time?
It's not. Here's example, where order is not retained:
const data = [
{
item: 'item1',
group: 'g2'
}, {
item: 'item2',
group: 'g3'
}, {
item: 'item3',
group: 'g1'
}, {
item: 'item4',
group: 'g2'
}, {
item: 'item5',
group: 'g3'
}
]
const groupedItems = _(data).groupBy(item => item.group).value()
In this case one would expect that group order would be: g2, g3, g1 - reality is that they are sorted g1, g2, g3.
You can re-sort them with original array though.
const groupedItems = _(data)
.groupBy(item => item.group)
.sortBy(group => data.indexOf(group[0]))
.value()
This will ensure original order of items.
The current implementation of _.groupBy is:
// An internal function used for aggregate "group by" operations.
var group = function(behavior) {
return function(obj, iteratee, context) {
var result = {};
iteratee = cb(iteratee, context);
_.each(obj, function(value, index) {
var key = iteratee(value, index, obj);
behavior(result, value, key);
});
return result;
};
};
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
_.groupBy = group(function(result, value, key) {
if (_.has(result, key)) result[key].push(value); else result[key] = [value];
});
Basically it iterates through each of the items in the collection in order (if the collection is array-like, which it would be after a sortBy), and pushes them to an array based on their key value.
So yes, I'm not sure if this is an "official" characteristic of _.groupBy, but it does preserve the order of array-like collections, and that's probably unlikely to change.
Function groupBy returns object. Object doesn't save property order.
Does JavaScript Guarantee Object Property Order?
But group arrays saves order, because thay are added with push function.

Categories

Resources