Update an array based on the value of object - javascript

Iam having an array of object named finalArr and and object named replaceJsonData. If replaceJsonData contains add =1 , then value of REQUEST_TYPE in finalArr should also become 1
finalArr = [{
REQUEST_TYPE: 'add',
TIMESTAMP: '1671636661867',
}, ]
let replaceJsonData = {
"REQUEST_TYPE": {
'add': 1,
'modify': 2
}
}
I tried like this way , but value itself is in the form a key
finalArr.map((ele)=>{
Object.entries(replaceJsonData ).forEach(
([replaceDataKey, replaceDataValue]) => {
if (ele[replaceDataKey]) {
ele[replaceDataKey]=replaceDataValue
}
}
)
});
Expected Output:
finalArr = [{
REQUEST_TYPE: 1,
TIMESTAMP: '1671636661867',
}, ]

Use the property of replaceDataValue that matches the old value of the property being updated: replaceDataValue[ele[replaceDataKey]]
let finalArr = [{
REQUEST_TYPE: 'add',
TIMESTAMP: '1671636661867',
}, ]
let replaceJsonData = {
"REQUEST_TYPE": {
'add': 1,
'modify': 2
}
};
finalArr.map((ele) => {
Object.entries(replaceJsonData).forEach(
([replaceDataKey, replaceDataValue]) => {
if (ele[replaceDataKey]) {
ele[replaceDataKey] = replaceDataValue[ele[replaceDataKey]];
}
}
)
});
console.log(finalArr);

Related

Create unique values from duplicates in Javascript array of objects

I have an array of duplicated objects in Javascript. I want to create an array of unique objects by adding the index of occurrence of the individual value.
This is my initial data:
const array= [
{name:"A"},
{name:"A"},
{name:"A"},
{name:"B"},
{name:"B"},
{name:"C"},
{name:"C"},
];
This is expected end result:
const array= [
{name:"A-0"},
{name:"A-1"},
{name:"A-2"},
{name:"B-0"},
{name:"B-1"},
{name:"C-0"},
{name:"C-1"},
];
I feel like this should be fairly simple, but got stuck on it for a while. Can you please advise how I'd go about this? Also if possible, I need it efficient as the array can hold up to 1000 items.
EDIT: This is my solution, but I don't feel like it's very efficient.
const array = [
{ name: "A" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
const sortedArray = _.sortBy(array, 'name');
let previousItem = {
name: '',
counter: 0
};
const indexedArray = sortedArray.map((item) => {
if (item.name === previousItem.name) {
previousItem.counter += 1;
const name = `${item.name}-${previousItem.counter}`;
return { name };
} else {
previousItem = { name: item.name, counter: 0};
return item;
}
});
Currently you are sorting it first then looping over it, which may be not the most efficient solution.
I would suggest you to map over it with a helping object.
const a = [{name:"A"},{name:"A"},{name:"A"},{name:"B"},{name:"B"},{name:"C"},{name:"C"},], o = {};
const r = a.map(({ name }) => {
typeof o[name] === 'number' ? o[name]++ : o[name] = 0;
return { name: `${name}-${o[name]}` };
});
console.log(r);
Keep a counter, and if the current name changes, reset the counter.
This version mutates the objects. Not sure if you want a copy or not. You could potentially sort the array by object name first to ensure they are in order (if that's not already an existing precondition.)
const array = [
{ name: "A" },
{ name: "A" },
{ name: "A" },
{ name: "B" },
{ name: "B" },
{ name: "C" },
{ name: "C" },
];
let name, index;
for (let i in array) {
index = array[i].name == name ? index + 1 : 0;
name = array[i].name;
array[i].name += `-${index}`;
}
console.log(array);
Another way, if you don't want to sort, and don't want to mutate any objects, is to use a map and keep track of the current index for each object.
const array = [
// NOTE: I put the items in mixed up order.
{ name: "A" },
{ name: "C" },
{ name: "A" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
let index = {};
let next = name => index[name] = index[name] + 1 || 0;
let result = array.map(obj => ({ ...obj, name: obj.name + '-' + next(obj.name) }));
console.log(result);

Get array of all unique object values based on property name

How can I get an array with all the unique values based on a property name?
In my case my object looks like this and I want an array with the unique documentID's.
const file = {
invoice: {
invoiceID: 1,
documentID: 5
},
reminders: [
{
reminderID: 1,
documentID: 1
},
{
reminderID: 2,
documentID: 1
}
]
}
The result should be an array [5, 1] //The unique documentID's are 5 and 1
It doesn't seem like possible to add a property name to the Object.values() function.
You can use Set to get unique documentID.
const file = {
invoice: {
invoiceID: 1,
documentID: 5
},
reminders: [
{
reminderID: 1,
documentID: 1
},
{
reminderID: 2,
documentID: 1
}
],
payments: {
documentID : 5
}
};
var keys = Object.keys(file).map(key=>file[key].map ? file[key].map(i=>i.documentID) : file[key].documentID)
var keysFlattened= [].concat.apply([], keys);
var unique = new Set(keysFlattened);
console.log(Array.from(unique));
I use something like this that does what you want I think
const keepUniqueBy = key => (array, item) => {
if (array.find(i => item[key] === i[key])) {
return array;
} else {
return [ ...array, item ];
}
};
Then you can simply: const unique = reminders.reduce(keepUniqueBy('documentID'))
NB: It's probably low performing, but for small arrays it doesn't matter.

array.map() not returning a single array

I have the code below which I expect to map the result from the nested array and return a single array having both id's but I get 2 arrays instead. Can someone please guide me on what I'm doing wrongly?
arrayVal = [{
sources: {
data: [{
id: 1
}]
}
},
{
sources: {
data: [{
id: 2
}]
}
}
]
for (let sub of arrayVal) {
let result = sub.sources.data.map(x => (x.id))
console.log(result)
}
Right now, you're calling map for each element in arrayVal, so you get two arrays. Use reduce instead, to transform an array of objects into another array that's not necessarily one-to-one with the input elements:
const arrayVal=[{sources:{data:[{id:1}]}},{sources:{data:[{id:2}]}}];
const result = arrayVal.reduce((a, { sources: { data } }) => (
[...a, ...data.map(({ id }) => id)]
), []);
console.log(result)
Try following
var arrayVal = [{sources: {data: [{id: 1}]}},{sources: {data: [{id: 2}]}}];
// Create an array on sources.data and merge it into 1 collection (array)
var result = arrayVal.reduce((a, c) => [...a, ...c.sources.data.map(({id}) => id)], []);
console.log(result);
For reference, Array.reduce
Also, you can improve your code as follows
var arrayVal = [{sources: {data: [{id: 1}]}},{sources: {data: [{id: 2}]}}];
let result = [];
for (let sub of arrayVal) {
result.push(sub.sources.data.map(x => (x.id)));
}
console.log([].concat(...result))
arrayVal = [{
sources: {
data: [{
id: 1
}]
}
},
{
sources: {
data: [{
id: 2
}]
}
}
]
let result = [];
for (let sub of arrayVal) {
result = result.concat(sub.sources.data.map(x => (x.id)))
}
console.log(result)
I think concat is what you were missing here, Hope this is what you trying to achieve
Try this
arrayVal = [{
sources: {
data: [{
id: 1
}]
}
},
{
sources: {
data: [{
id: 2
}]
}
}
]
let result = arrayVal.map((x) => x.sources.data[0].id)
console.log(result)
You can do something like this:
arrayVal = [{
sources: {
data: [{
id: 1
}]
}
},
{
sources: {
data: [{
id: 2
}]
}
}
]
var flat = arrayVal.reduce(function(prev,curr,cI){
prev.push(curr.sources.data.map(x => (x.id))[0]);
return prev; // ********* Important ******
}, []);

Merge array of objects with underscore

I have array of objects like this. And they have duplicated property 'contactName' values
[
{
categoryId:1
categoryName:"Default"
contactId:141
contactName:"Anonymous"
name:"Mobile"
value:"+4417087654"
},
{
categoryId:1
categoryName:"Default"
contactId:325
contactName:"Anonymous"
name:"Email"
value:"test2#gmail.com"
},
{
categoryId:1
categoryName:"Default"
contactId:333
contactName:"Anonymous"
name:"Email"
value:"ivdtest#test.com"
}
]
I want to merge them in one object by the name of property 'contactName'
To something like this
[
{
categoryId: 1,
categoryName: "Default",
contactId: 141,
contactName: "Anonymous",
names: {
1: "Mobile",
2: "Email",
3: "Email"
},
values: {
1: '+2234324',
2: "ivdtest#test.com",
3: "test2#gmail.com"
}
}
];
Edit: How can I group objects also by categoryName ?
var grouped = _.groupBy(input, 'contactName');
var output = _.map(grouped, function(entries) {
return _.extend(
_.pick(entries[0], 'categoryId', 'categoryName', 'contactId', 'contactName'),
{
names: _.indexBy(_.pluck(entries, 'name'), function(val, index) { return index +1; }),
values: _.indexBy(_.pluck(entries, 'value'), function(val, index) { return index +1; })
}
);
});
https://jsfiddle.net/f1x4tscu/3/
Another variant with array inside the object
var grouped = _.groupBy(this.contacts, 'contactName');
var output = _.map(grouped, function (entries) {
return _.extend(
_.pick(entries[0], 'categoryId', 'categoryName', 'contactId', 'contactName'),
{
addresses: _.map(entries, function (m) {
return {
name: m.name,
value: m.value
}
}),
}
);
});

javascript how to count the object and combin

I get the data from database like this:
var json = [
{
name: "one",
roles: [
{ role: "admin",state: 1 },
{ role: "operator",state: 1 },
{ role: "admin",state: 1 }
]
},
{
name: "two",
roles: [
{ role: "admin2",state: 0 },
{ role: "operator",state: 1 },
{ role: "admin",state: 1 }
]
}
];
And I want to become this
=>
var json = [
{
name: "one",
roles:[...],
data: [
{ "admin": 2,"eable": 2,"disable":0 },
{ "operator": 1,"eable": 1,"disable":0}
]
},
{
name: "two",
roles:[...],
data: [
{ "admin": 1,"eable": 0,"disable":1 },
{ "admin2": 1,"eable": 1,"disable":0},
{ "operator": 1,"eable": 1,"disable":0}
]
}
];
I'm getting stuck now, don't know what to do,please help.
Here is what I tried:
json.forEach(function(v,k){
var ret = {
"enable":0,
"disable":0
}
json[k]['data'] = [];
json[k]['roles'].forEach(function(v,k){
json[k]['data'].push( v['role'] );
})
});
http://jsfiddle.net/B9XkX/1/
This is a lot to chew on because the data structure is weird but bear with me:
result = json.map(function(obj){
// we can use map here to transform each object, whatever we return will
// go into the result array.
var roles = obj.roles.reduce(function(memo, item){
// we need to turn a role object into a data object
// but because we are counting the number of eable
// and disable states we need to make a discreet object
// that can hold the numbers without worrying about the
// final data structure.
memo[item.role] = memo[item.role] || {};
memo[item.role].eable = memo[item.role].eable || 0;
memo[item.role].disable = memo[item.role].disable || 0;
// we initialize the memo object if we haven't seen the
// role before.
if (item.state === 1) {
// we count eable for one state
memo[item.role].eable += 1;
} else if (item.state === 0) {
// we count disable for the other state
memo[item.role].disable += 1;
}
return memo;
}, {});
// now the roles object looks something like this:
/**
* {
* admin: {eable: 2, disable: 0},
* operator: {eable: 1, disable: 0}
* }
**/
return {
name: obj.name,
roles: obj.roles,
data: Object.keys(roles).map(function(key){
// now we need to turn the roles object back into an array, so we use
// Object.keys method to turn the keys on the roles object into an array
// and we use map again to setup an object that we will use instead.
var item = {};
item[key] = 1; // {admin: 1}
item.eable = roles[key].eable; // {admin:1, eable: 2}
item.disable = roles[key].disable; // {admin:1, eable: 2, disable: 0}
return item;
})
}
});

Categories

Resources