flatten an array of objects, while also considering for uniqueness - javascript

I have the following array of objects.
var array = [
{
name: 'abc',
place1: 'def'
},
{
name: 'abc',
place2: 'ghi'
}]
I am trying to get the following output
var array = [[name:'abc'],[place1:'def'],[place2:'ghi']]
this is my attempt:
let arr = []
array.forEach((element,index) => {
const keys = Object.keys(element)
keys.forEach(e => {
let temp = [];
temp[0] = e;
temp[1] = element[e];
if(!arr.indexOf(temp)
arr.push(temp)
});
});
but I am not getting the expected output.

I'm not sure how a an array of objects with different properties would help you. You should probably use one object with all properties or an array of entries.
However, to get the result you want - merge the array of objects to a single object by spreading into Object.assign() to remove duplicates. Then convert to an array of entries [key, value], and map back to an array of objects:
const array = [{"name":"abc","place1":"def"},{"name":"abc","place2":"ghi"}]
const result = Object.entries(Object.assign({}, ...array))
.map(([k, v]) => ({ [k]: v })) // remove the map to get an array of entries
console.log(result)

Related

convert 2 arrays into key value object, one array hold the keys, they second is nested array of matching indexed values

combine each irritation of valueArr it's inner member to a matching key from keysArr,
Index will always match each other.
the result I'm looking for: the key for each object and the id is equal to "internalid"
But i will work it out if it's not clear
const valuesArr =
["10","9","Item","Bank","2","true","true","Result7","5675"],
["9","1","Expenses","OthExpense","4","true","true","9999","9999"],
["8","8","Expenses","OthAsset","6","false","false","6666","77777"],
["7","8","Expenses","AcctPay","4","true","true","666","7777"],
["6","123","123","123","123","123","123","123","123"],
["5","123","123","123","123","123","123","123","123"],
["4","Test1","Item","OthCurrAsset","2","Result5","Result6","ytrytrytryrty","32432"],
["2","Result1","Result2","Result3","Result4","Result5","Result6","Result7","Result8"],
["1","Test1","Test12","Test13","Test14","Test15","Test16","Test17","Test18"]]
const keysArr =
["internalid",
"custrecord_st_segment_transaction_type",
"custrecord_st_segment_sublist",
"custrecord_st_segment_account_type",
"custrecord_st_segment_subsidiary",
"custrecord_st_segment_department",
"custrecord_st_segment_class",
"custrecord_st_segment_location",
"custrecord_st_segment_custom_segment"]
result:
{"1":{"id":"1","values":{"internalid":"1","custrecord_st_segment_transaction_type":"Test1","custrecord_st_segment_sublist":"Test12","custrecord_st_segment_account_type":"Test13","custrecord_st_segment_subsidiary":"Test14","custrecord_st_segment_department":"Test15","custrecord_st_segment_class":"Test16","custrecord_st_segment_location":"Test17","custrecord_st_segment_custom_segment":"Test18"}},
"2":{"id":"2","values":{"internalid":"2","custrecord_st_segment_transaction_type":"Result1","custrecord_st_segment_sublist":"Result2","custrecord_st_segment_account_type":"Result3","custrecord_st_segment_subsidiary":"Result4","custrecord_st_segment_department":"Result5","custrecord_st_segment_class":"Result6","custrecord_st_segment_location":"Result7","custrecord_st_segment_custom_segment":"Result8"}},
"4":{"id":"4","values":{"internalid":"4","custrecord_st_segment_transaction_type":"Test1","custrecord_st_segment_sublist":"Item","custrecord_st_segment_account_type":"OthCurrAsset","custrecord_st_segment_subsidiary":"2","custrecord_st_segment_department":"Result5","custrecord_st_segment_class":"Result6","custrecord_st_segment_location":"ytrytrytryrty","custrecord_st_segment_custom_segment":"32432"}},
"5":{"id":"5","values":{"internalid":"5","custrecord_st_segment_transaction_type":"123","custrecord_st_segment_sublist":"123","custrecord_st_segment_account_type":"123","custrecord_st_segment_subsidiary":"123","custrecord_st_segment_department":"123","custrecord_st_segment_class":"123","custrecord_st_segment_location":"123","custrecord_st_segment_custom_segment":"123"}},
"6":{"id":"6","values":{"internalid":"6","custrecord_st_segment_transaction_type":"123","custrecord_st_segment_sublist":"123","custrecord_st_segment_account_type":"123","custrecord_st_segment_subsidiary":"123","custrecord_st_segment_department":"123","custrecord_st_segment_class":"123","custrecord_st_segment_location":"123","custrecord_st_segment_custom_segment":"123"}},
"7":{"id":"7","values":{"internalid":"7","custrecord_st_segment_transaction_type":"8","custrecord_st_segment_sublist":"Expenses","custrecord_st_segment_account_type":"AcctPay","custrecord_st_segment_subsidiary":"4","custrecord_st_segment_department":"true","custrecord_st_segment_class":"true","custrecord_st_segment_location":"666","custrecord_st_segment_custom_segment":"7777"}},
"8":{"id":"8","values":{"internalid":"8","custrecord_st_segment_transaction_type":"8","custrecord_st_segment_sublist":"Expenses","custrecord_st_segment_account_type":"OthAsset","custrecord_st_segment_subsidiary":"6","custrecord_st_segment_department":"false","custrecord_st_segment_class":"false","custrecord_st_segment_location":"6666","custrecord_st_segment_custom_segment":"77777"}},
"9":{"id":"9","values":{"internalid":"9","custrecord_st_segment_transaction_type":"1","custrecord_st_segment_sublist":"Expenses","custrecord_st_segment_account_type":"OthExpense","custrecord_st_segment_subsidiary":"4","custrecord_st_segment_department":"true","custrecord_st_segment_class":"true","custrecord_st_segment_location":"9999","custrecord_st_segment_custom_segment":"9999"}},
"10":{"id":"10","values":{"internalid":"10","custrecord_st_segment_transaction_type":"9","custrecord_st_segment_sublist":"Item","custrecord_st_segment_account_type":"Bank","custrecord_st_segment_subsidiary":"2","custrecord_st_segment_department":"true","custrecord_st_segment_class":"true","custrecord_st_segment_location":"Result7","custrecord_st_segment_custom_segment":"5675"}}]
I think the OP is asking how to "zip" two arrays, where one has keys and one has values. If so, Object.fromEntries() is very useful.
A simple zip, goes like this:
// a simple zip
function zip(keys, values) {
return Object.fromEntries(
keys.map((key, index) => [key, values[index]])
);
}
The OP appears to want the lead element in the values array to be a specially named field in the new object as well as the key of the resulting object. Here, applying the simple zip...
function zip(keys, values) {
return Object.fromEntries(
keys.map((key, index) => [key, values[index]])
);
}
// the value array contains an "id" element at the start
// produce an object that looks like { id: number, values: {...} }
function objectFromValues(keys, values) {
return { id: values[0], values: zip(keys, values.slice(1)) }
}
const valuesArr = [
[1, "A", "B", "C"],
[2, "D", "E", "F"]
];
const keys = ["keyA", "keyB", "keyC"];
const result = valuesArr.reduce((acc, values) => {
acc[values[0]] = objectFromValues(keys, values);
return acc;
}, {});
console.log(result)

Find the element in json - Using underscore library or other way

I want to find the g:id object in the below given array of objects
If my g:id is like "g:id": "121"
I can find the element like
var item = _.findWhere(obj, {'g:id': '121'});
But what i have is "g:id": ["121"] like an array. How can i find it.
Here's my array of objects.
[
{
"g:id": [
"121"
],
"g:item_group_id": [
"90461"
]
},
{
"g:id": [
"129"
],
"g:item_group_id": [
"90462"
]
}
]
I tried like this var item = _.findWhere(jsonXML, {'g:id'.[0]: '121'}); but it is not valid.
How can i do this by underscore.js or any other way ?
You can use Array.find() with destructuring to get the g:id value from the array:
const arr = [{"g:id":["121"],"g:item_group_id":["90461"]},{"g:id":["129"],"g:item_group_id":["90462"]}]
const result = arr.find(({ 'g:id': [gid] }) => gid === '121')
console.log(result)
Another option is to use Array.includes() to see if the array contains the value (a must if the array may contain more the one value):
const arr = [{"g:id":["121"],"g:item_group_id":["90461"]},{"g:id":["129"],"g:item_group_id":["90462"]}]
const result = arr.find(({ 'g:id': gid }) => gid.includes('121'))
console.log(result)

ES6 way - Get unique values from a nested array by key

trying to improve my JS chops.
Is there a cleaner way to retrieve the property value from the array below, by key, from a nested object, removing duplicates and sorting them alphabetically?
Here's what I have:
getObjectValues(array, key){
var unique = [];
array.forEach(function(item){
item[key].forEach(function(value){
if (unique.indexOf(value) < 0) {
unique.push(value)
}
})
});
return unique.sort();
},
example array of object:
[
{ name: 'hello', value: ['a','b','c']},
{ name: 'hello', value: ['a','b','c']},
{ name: 'hello', value: ['a','b','c']}
]
expected output should be an array:
var array = ['a','b','c']
You could just use a Set, and add all the items to it:
let arr = [
{ name: 'hello', value: ['a','b','c']},
{ name: 'hello', value: ['a','b','c']},
{ name: 'hello', value: ['a','b','c']}
]
console.log(
Array.from(
new Set(
arr.reduce(
(carry, current) => [...carry, ...current.value],
[]
)
)
).sort()
)
If you need something concise, you may go as simple as that:
make use of Set to get rid of duplicates
employ Array.prototype.flatMap() (with slight touch of destructuring assignment) to extract value items from within all objects into single array
const src = [{name:'hello',value:['c','b','d']},{name:'hello',value:['e','b','c']},{name:'hello',value:['f','a','e']}],
result = [...new Set(src.flatMap(({value}) => value))].sort()
console.log(result)
.as-console-wrapper{min-height:100%;}
If you need something really fast, you may do the following:
use Array.prototype.reduce() to turn your array into Set of unique records (looping through value items with Array.prototype.forEach and doing Set.prototype.add())
spread resulting Set into array and .sort() that
const src = [{name:'hello',value:['c','b','d']},{name:'hello',value:['e','b','c']},{name:'hello',value:['f','a','e']}],
result = [...src.reduce((acc,{value}) =>
(value.forEach(acc.add, acc), acc), new Set())].sort()
console.log(result)
.as-console-wrapper{Min-height:100%;}

Grouping with Lodash

I'm trying to group by "date" an object like this:
let myObj = [
{"date":"01/12","Deposits":50000},
{"date":"01/12","Withdrawals":10000}
]
So if I did groupBy "date", I'd want to receive:
[
{"date":"01/12", "Deposits":50000, "Withdrawals":10000}
]
I tried many different ways without success =(
Here is an approach without lodash, by using .reduce() and the spread syntax ... to extract your wanted properties. By using .reduce() you can group your array's objects into a larger aggregation object (ie: the acc), which you can then get the values() of to get your array of results:
const myObj = [{"date":"01/12","Deposits":50000},{"date":"01/12","Withdrawals":10000}];
const res = Object.values(myObj.reduce((acc, {date, ...rest}) => {
acc[date] = {...(acc[date] || {date}), ...rest};
return acc;
}, {}));
console.log(res);
If you wish to use lodash, here is an approach using _.groupBy(), _.map(), _.assign() and _.flow() which will allow you to make your own function to merge arrays by a key:
const myObj = [{"date":"01/12","Deposits":50000}, {"date":"01/12","Withdrawals":10000}];
const mergeArr = _.flow(
arr => _.groupBy(arr, 'date'),
group => _.map(group, arr => _.assign({}, ...arr))
);
const res = mergeArr(myObj);
console.log(res);
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>
let result = _.map(_.groupBy(myObj, 'date'), value => _.assign(...value));

Converting flat array to Id and Name object array using Lodash

let states = ["Georgia","California","FL","TX","MA","NJ"];
How do I convert the states array into Id and Name array collection using lodash.
Is there a way to convert the array in below format ( image shown below):
You don't really need lodash to do that.
let states = ["Georgia","California","FL","TX","MA","NJ"];
let result = states.map((item) => {
return {
id: item,
name: item}})
console.log(result)
You do pretty much the same with lodash
import _ from 'lodash';
result = _.map(states, (item) => {
return {
id: item,
name: item}})
let states = ["Georgia","California","FL","TX","MA","NJ"];
const newObj = [];
_.each(states, state => newObj.push({ id: state, name: state }));
console.log(newObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
_.each performs a function on each item of an Array. With that you can create a new object for each state and push that into a new Array. Note: this could also be accomplished with JavaScript's built in .map.
----- UPDATE -----
Why did I make this complicated many years ago?
const states = ["Georgia","California","FL","TX","MA","NJ"];
const newObj = states.map(state => ({ id: state, name: state }));
console.log(newObj);
No need to use lodash, just map through the array and return a new object for each item in the array.

Categories

Resources