Remove array of object if object inside is empty - javascript

I am preparing an array like this
datas[5] = { "qty_sized": "1", "resolution": "5", "status": "", "order": 1342 };
where [5] is dynamic from response.
I have and object mydata and inside that I have a object items.
I push array to object items, with assign
Object.assign(mydatadata.items, datas);
Now mydata.items has an array set,
`
items{
1 {qty_auth: "", resolution: "4", status: "", order: "1495"},
5 {qty_sized: "1", resolution: "4", status: "", order: "1485"}
}`
Now if qty_auth: "" , from which i need to check if qty_ is empty then remove the array . So expected output is something like this:
Note: qty_ is dynamic here.
items{ 5 {qty_sized: "1", resolution: "4", status: "", order: "1485"} }
and i want to result inside same object mydata.items
I tried something like this
const mydatadata.items = mydata.items.filter((o) =>
Object.keys(o).some((k) => k.startsWith("qty") && o[k])
);
console.log(result);
but its now giving me any output

Using Object#entries, get the key-value pairs of items
Using Array#filter, iterate over the above array
In each iteration, check if the current item has a key starting with qty_ whose value is not empty. You can do this using Object#keys, Array#some, and String#startsWith.
Using Object#fromEntries, convert the filtered pairs to an object again.
const obj = {
items: {
1: {qty_auth: "", resolution: "4", status: "", order: "1495"},
5: {qty_sized: "1", resolution: "4", status: "", order: "1485"}
}
};
obj.items = Object.fromEntries(
Object.entries(obj.items)
.filter(([_, item]) =>
Object.keys(item).some(key => key.startsWith('qty_') && item[key])
)
);
console.log(obj);

You're talking about an array, but using curly brackets instead of square brackets. For filter() to work it would have to look like:
mydata = {
items: [
{qty_auth: "", resolution: "4", status: "", order: "1495"},
{qty_sized: "1", resolution: "4", status: "", order: "1485"}
]
}
Assuming it is an actual array there's still a problem with "const mydatadata.items", or at least it throws an error for me because mydatadata is not initialized. Unless it's a typo and it should be mydata, but then you'd be redeclaring it. So depending on what you want:
mydata.items = mydata.items.filter((o) =>
Object.keys(o).some((k) => k.startsWith("qty") && o[k])
);
or
let mydatadata = {};
mydatadata.items = mydata.items.filter((o) =>
Object.keys(o).some((k) => k.startsWith("qty") && o[k])
);
Furthermore you're storing the result in mydatadata but you're logging the variable result.
So depending on the previous answer:
console.log(mydatadata);
or
console.log(mydata);
Here's a fiddle: https://jsfiddle.net/b57qa82d/

You should probably just be using an array rather than an object. It's not really clear from your question what structure you need as you keep changing the terminology to describe your data. For example: "Now mydata.items has an array set" but your code says that it should be object with keys, not an array.
So I suggest: get your data in an array, and filter it by iterating over each object's entries and checking to see if any of the keys starting with "qty" has a value that isn't an empty string. You can then assign that filtered array to myObject.items.
const data = [
{ "qty_sized": "0", "resolution": "5", "status": "", "order": 2 },
{ "qty_auth": "", "resolution": "5", "status": "", "order": 3 },
{ "qty_auth": "1", "resolution": "5", "status": "", "order": 1342 },
{ "qty_sized": "", "resolution": "2", "status": "", "order": 1 },
{ "qty_sized": "1", "resolution": "1", "status": "", "order": 142 }];
const filtered = data.filter(obj => {
return Object.entries(obj).find(([key, value]) => {
return key.startsWith('qty') && value;
});
});
const myObject = { items: filtered };
console.log(myObject);
Additional documentation
Object.entries
find

Related

javascript how to replace data where id match

I have a data like this in array.
[
{
"teamName": "TeamA",
"players": ["1","2"]
},
{
"teamName": "TeamB",
"players": ["2"]
}
]
and I want to replace players id which match in other array
players = [
{
"id": "1",
"playername": "alex"
},
{
"id": "2",
"playername": "john"
}
]
So output will be like this
[
{
"teamName": "TeamA",
"players": [
{
"id": "1",
"playername": "alex"
},
{
"id": "2",
"playername": "john"
}]
},
{
"teamName": "TeamB",
"players": [
{
"id": "2",
"playername": "john"
}]
}
]
I tried to find by for loop and where it will find and replace but that's not working for me.
you can do this by iterating over first array and updating the players property of each element in that array.
let arrOne = [
{
"teamName": "TeamA",
"players": ["1","2"]
},
{
"teamName": "TeamB",
"players": ["2"]
}
]
players = [
{
"id": "1",
"playername": "alex"
},
{
"id": "2",
"playername": "john"
}
]
// solution
arrOne.forEach( teamObject => {
let newPlayerArray = [];
teamObject.players.forEach( id => {
let newPlayerObject = {};
newPlayerObject.id = id;
newPlayerObject.playername = players.find( player => player.id == id)?.playername;
newPlayerArray.push(newPlayerObject)
})
teamObject.players = newPlayerArray;
})
One approach:
// defining the variables, naming 'teams' as it was unnamed in
// the original post:
let teams = [
{
"teamName": "TeamA",
"players": ["1", "2"]
},
{
"teamName": "TeamB",
"players": ["2"]
}
],
// updated the name of this Array of Objects due to the naming
// clash between the original name ('players') when using
// destructuring assignments while iterating the 'teams' Array,
// because of an identically-named property:
playerDetails = [{
"id": "1",
// I updated this property-name to use camelCase consistently:
"playerName": "alex"
},
{
"id": "2",
"playerName": "john"
}
],
// rather than editing the original Array, we create a new one
// by iterating over the teams Array, using Array.prototype.map():
combined = teams.map(
// using destructuring assignement to retrieve the named properties
// of the Object passed in to the function:
({
teamName,
players
}) => {
// because we're returning an Object literal, we have to use return and wrap
// the anonymous callback function of the Arrow function in curly braces ('{...}')
// to avoid the returned Object-literal being misinterpreted as a function body:
return {
// we return the teamName property unchanged:
teamName,
// but here we update the players property, we iterate over the players Array,
// again using players.prototype.map() to update the existing Array based on the
// result of actions taken in the anonymous Arrow function:
players: players.map(
// we pass in a reference to the 'id' enclosed within the player Array,
// giving it a verbose/clear name given that 'id' would be a sensible/short
// name, but is used within the enclosed function as the named property of
// the other function we're working with.
// within the anonymous function we use Array.prototype.find():
(teams_playerID) => playerDetails.find(({
// passing in a reference to the 'id' property-name of the Object
// within the playerDetails Array:
id
// and here we check to see if the 'id' of the playerDetails Array is
// exactly-equal to the teams_playerID variable; if so this Object is
// returned and the 'players' Array is updated, and changed from a String
// to the found Object; if no match is found the current 'players' Array-value
// is unchanged:
}) => id == teams_playerID ))
}
});
console.log(combined);
// [{"teamName":"TeamA","players":[{"id":"1","playerName":"alex"},{"id":"2","playerName":"john"}]},{"teamName":"TeamB","players":[{"id":"2","playerName":"john"}]}]
JS Fiddle demo.
References:
Array.prototype.find().
Array.prototype.map().
Arrow functions.
Destructuring assignemnt.
You can build the result by stepping through the list of teams, looking up each player by their id, and adding the player record to the result’s players array.
const teams = [
{
"teamName": "TeamA",
"players": ["1", "2"]
},
{
"teamName": "TeamB",
"players": ["2"]
}
]
const players = [
{
"id": "1",
"playername": "alex"
},
{
"id": "2",
"playername": "john"
}
]
let result = []
teams.forEach(team => {
let record = {
"teamname": team.teamName,
"players": []
}
team.players.forEach(player_id => {
record.players.push(players.find(p => p.id === player_id))
})
result.push(record)
})
console.log(JSON.stringify(result, null, 4))

Update the object value based on array index [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have 2 object in array
dataV[1] = {
"resolution": "4"
};
datas[1] = {
{qty_approved: "1", resolution: "5", status: "", order: "1332"}
}
if both index same then i want to update with the value from 1st. I want to update resolution value to 4 from 5. Based on upcoming value from new array value in dataV
Expected output like this :
datas[1] = {
{qty_auth: "1", resolution: "4", status: "", order: "1332"}
}
Wherever you're updating the value of dataV you can do something like this, to update the datas:
datas = datas.map((data, i) => {
return { ...data, resolution: dataV[i].resolution };
});
And if you're using react you can do the same thing in useEffect with dataV as a dependency. So, whenever dataV changes, datas will change automatically.
let array1 = [
{
resolution: '4',
},
];
let array2 = [
{ qty_approved: '1', resolution: '5', status: '', order: '1332' },
];
let array3 = array1.map((element, index) => {
if (typeof array2[index] != 'undefined') {
return { ...array2[index], ...element};
}
return element;
});
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
Since you can get the corresponding element by array index, you can get the corresponding resolution as easy as the following snippet:
datas.forEach( (_, i) => {
datas[i].resolution = dataV[i].resolution
})
Using Array#reduce, iterate over dataV while updating a Map where the index is the key and the resolution is the value
Using Array#forEach, iterate over datas, if the above map has a key of such index, update the resolution
const
dataV = [ { "resolution": "4" }, { "resolution": "7" }, { "resolution": "1" } ],
datas = [
{ qty_approved: "1", resolution: "5", status: "", order: "1332" },
{ qty_approved: "1", resolution: "3", status: "", order: "1331" },
{ qty_approved: "1", resolution: "9", status: "", order: "1333" },
];
const indexResolutionMap = dataV.reduce((map, { resolution }, i) =>
map.set(i, resolution)
, new Map);
datas.forEach((e, i) => {
const resolution = indexResolutionMap.get(i);
if(resolution) e.resolution = resolution;
});
console.log(datas);
The following approach is going to map each item of datas. The mapping function nevertheless will be a real function (not an arrow function), thus it is aware of map's second thisArg argument which for the OP's use case will be the dataV array where one wants to read the resolution values from.
The advantage of such an approach is, that one can work with a reusable mapper function which is agnostic to outside array references because it does process an array while the related/corresponding array gets provided as the mapper functions this context.
The mapping functionality itself does try to not mutate the original item reference by loosely decoupling the reference via creating a shallow copy of the entire item. On top the resolution value which was read from the corresponding array via this[idx].resolution gets assigned to the just created shallow copy.
const datas = [
{ qty_approved: "1", resolution: "5", status: "", order: "1332" },
{ qty_approved: "1", resolution: "3", status: "", order: "1331" },
{ qty_approved: "1", resolution: "9", status: "", order: "1333" },
];
const dataV = [{
"resolution": "4",
}, {
"resolution": "7",
}, {
"resolution": "1",
}];
// mapping approach.
function copyItemAndAssignSameIndexResolutionFromTargetArray(item, idx) {
// - this merge pattern is agnostic about an `item`'s structure.
// - `item` could feature more keys but just `resolution` gets reassigned.
return Object.assign({}, item, { resolution: this[idx].resolution });
}
console.log(
'mapped version of changed `dataV` items ...',
datas.map(copyItemAndAssignSameIndexResolutionFromTargetArray, dataV)
);
console.log('still unmutated `datas` ...', { datas });
.as-console-wrapper { min-height: 100%!important; top: 0; }
In case the OP wants to mutate each of the datas array's items, the above introduced mapper function changes slightly in order to be utilized by a context aware forEach ...
const datas = [
{ qty_approved: "1", resolution: "5", status: "", order: "1332" },
{ qty_approved: "1", resolution: "3", status: "", order: "1331" },
{ qty_approved: "1", resolution: "9", status: "", order: "1333" },
];
const dataV = [{
"resolution": "4",
}, {
"resolution": "7",
}, {
"resolution": "1",
}];
// mapping approach.
function assignSameIndexResolutionFromTargetArray(item, idx) {
item.resolution = this[idx].resolution;
// Object.assign(item, { resolution: this[idx].resolution });
}
datas.forEach(assignSameIndexResolutionFromTargetArray, dataV);
console.log('mutated `datas` array ...', { datas });
.as-console-wrapper { min-height: 100%!important; top: 0; }
Or (desperately guessing) is the OP looking for a solution where a datas item has to be updated/mutated by an explicitly provided dataV item? Something like this?..
const datas = [
{ qty_approved: "1", resolution: "3", status: "", order: "1331" },
{ qty_approved: "1", resolution: "5", status: "", order: "1332" },
{ qty_approved: "1", resolution: "9", status: "", order: "1333" },
];
const dataV = [{
"resolution": "1",
}, {
"resolution": "4",
}, {
"resolution": "7",
}, ];
function updateResolution(targetArray, sourceArray, resolutionItem) {
const updateIndex =
sourceArray.findIndex(item =>
item.resolution === resolutionItem.resolution
);
targetArray[updateIndex].resolution = resolutionItem.resolution;
return targetArray[updateIndex];
}
console.log(
'updateResolution(datas, dataV, { resolution: "4"}) ...',
updateResolution(datas, dataV, { resolution: "4"})
);
console.log('mutated `datas` array ...', { datas });
console.log(
'updateResolution(datas, dataV, { resolution: "7"}) ...',
updateResolution(datas, dataV, { resolution: "7"})
);
console.log('mutated `datas` array ...', { datas });
.as-console-wrapper { min-height: 100%!important; top: 0; }

Merging nested array using map in JS

I am fetching a data from Laravel API this way
$inventory = Gifts::with('allocation')->get();
$response = [
'data' => $inventory->toArray(),
]
The output for the above looks like the image below in the console
This is what is inside the 0: {…}
{
"id": 1,
"name": "Bar 1",
"allocation": [
{
"id": 1,
"location_id": "1",
"qty": "2",
},
{
"id": 2,
"location_id": "4",
"qty": "32",
},
{
"id": 3,
"location_id": "7",
"qty": "12",
}
]
}
I'm trying to get an output like this
{
"isEditable": false,
"id": 1,
"name": "Bar 1",
"location1": "2"
"location4": "32"
"location7": "12"
}
It's an array that consists of 100+ entries like this and the allocation can be more or less or maybe empty as well
What I have done so far
const array = result.data(gift => ({ isEditable: false, ...gift }));
This adds "isEditable" field to the array.
You could use Array.prototype.map() to map the result array into a new one that only includes id, name, and the locationNN properties.
In the Array.prototype.map()'s callback:
Use the spread operator to separate the allocation property from the other properties of each array item (call it otherProps e.g.):
Spread the otherProps into a new object, inserting the isEditable property.
Map the allocation items into a key-value pair array, where the key is location_id appended to "location"; and the value is the qty property.
Use Object.fromEntries() on the key-value pair array to create an object, and spread that object into the outer object to be returned.
const output = result.map(r => {
const { allocation, ...otherProps } = r 1️⃣
return {
...otherProps, 2️⃣
isEditable: false,
...Object.fromEntries( 4️⃣
allocation.map(a => [`location${a.location_id}`, a.qty]) 3️⃣
)
}
})
demo
This solution uses reduce
const { allocation, ...rest } = gift
const processed = allocation.reduce((acc, loc, idx) => {
acc[`location${loc.location_id}`] = loc.qty
return acc
}, {})
const result = { ...rest, ...processed }
console.log(result)

Removing unwanted object keys & undefined in Javascript?

This is my array:
const
array1 = [
{
"value": "0",
"name": "5",
"waste": "remove",
"city": "NY"
},
{
"value": "0",
"name": "51",
"waste": "remove",
}
]
So now, i wanted to remove certain and form a new array with objects: For example, i need to remove "Waste & value" and keep rest of the things, so i used this code:
var keys_to_keep = ['name', 'city']
const result = array2.map(e => {
const obj = {};
keys_to_keep.forEach(k => obj[k] = e[k])
return obj;
});
console.log(result)
And it gives a output as
[ { name: '5', city: 'NY' }, { name: '51', city: undefined } ]
Now as you can see city with undefined value, how to remove that ? i mean filter this and just show keys with value,
So my question is how to filter undefined and also is there any other better solution for removing unwanted object keys and showing new array with wanted keys ? or the method am using is performant enough ?
You can check if the value is undefined in your forEach:
const result = array2.map(e => {
const obj = {};
keys_to_keep.forEach(k => {
if (undefined !== e[k]) {
obj[k] = e[k]
}
)
return obj;
});
You can check if e[k] is defined before you add it to obj by checking whether the e object has the property k using .hasOwnProperty():
const array = [{ "value": "0", "name": "5", "waste": "remove", "city": "NY" }, { "value": "0", "name": "51", "waste": "remove", } ];
const keys_to_keep = ['name', 'city'];
const result = array.map(e => {
const obj = {};
keys_to_keep.forEach(k => {
if (e.hasOwnProperty(k))
obj[k] = e[k]
});
return obj;
});
console.log(result)
If the keys you want to remove aren't dynamic, you can also use destructuring assignment to pull out the properties you want to discard, and use the rest syntax to obtain an object without those properties:
const array = [{ "value": "0", "name": "5", "waste": "remove", "city": "NY" }, { "value": "0", "name": "51", "waste": "remove", } ];
const result = array.map(({value, waste, ...r}) => r);
console.log(result)
I am going to answer both the parts. So here are the steps to do that.
Use map() on the main array.
Get entries of each object using Object.entries().
Apply filter() on entires array are remove those entires for which key is not present in keys_to_keep
Now for the second part.
Using keys_to_keep create an object which contain undefined values for each key.
Use map() again on prev result and use Spread operator. First spread the object created above and then spread the original values. This way if any key is not found it will be set to undefined
const
array1 = [
{
"value": "0",
"name": "5",
"waste": "remove",
"city": "NY"
},
{
"value": "0",
"name": "51",
"waste": "remove",
}
]
var keys_to_keep = ['name', 'city']
let obj = Object.fromEntries(keys_to_keep.map(x => [x, undefined]));
const res = array1.map(obj =>
Object.fromEntries(
Object.entries(obj).filter(([k, v]) => keys_to_keep.includes(k))))
.map(x => ({...obj, ...x}))
console.log(res)
You can use .map to iterate over the objects, Object.entries to get the key-value pairs of each item, Object.fromEntries to group them into the resulting objects, and .filter to get only the entries with a key in keys_to_keep and a value that is not undefined:
const array1 = [
{ "value": "0", "name": "5", "waste": "remove", "city": "NY" },
{ "value": "0", "name": "51", "waste": "remove" }
];
var keys_to_keep = ['name', 'city'];
const result = array1.map(item =>
Object.fromEntries(
Object.entries(item).filter(([key, value]) =>
keys_to_keep.includes(key) && value !== undefined
)
)
);
console.log(result)

Iterate through the child objects and get all the values with javascript

var formmd = {
"frmType": "Registration",
"frmStage": "step1-complete",
"formattr": {
"SystemUser": {
"LoginName": "A#test.com",
"Password": "password",
"PIN": "",
"IsTestUser": false
},
"ConsumerAddress": {
"AddressLine1": "201 MOUNT Road",
"AddressLine2": null,
"AddressTypeId": "1",
"City": "OLA TRAP",
"State": "NM",
"Zipcode": "60005"
},
"ConsumerPhone": {
"PhoneTypeId": 6,
"PhoneNumber": "9876543210",
"PrimaryPhoneIndicator": null,
"AllowVoicemail": false
},
"PhysicianSpecialty": {
"SpecialtyList": [
"1",
"2"
]
},
}
}
I'm trying to fetch all the values of the child objects under formattr but I'm unable to iterate inside the child objects. The following is the script I tried.
My Result should be
"A#test.com"
"password"
"PIN": ""
False
201 MOUNT Road"
The script I tried is
function walk(formmd) {
var obj1 = formmd.formattr;
for(var key in obj1){
if (obj1.hasOwnProperty(key)) {
var val1 = obj1[key];
if(val1.hasOwnProperty(key)){
for(var key in val1){
var val2 =val1[key];
console.log("val2");
}
}
}
}
}
How to access the keys of child objects in an automated way?
Try like this
for (var key in formmd) {
var val1 = formmd[key];
if (key=="formattr") {
for (var key1 in val1) {
var val2 = val1[key1];
for(var key2 in val2)
console.log(val2[key2]);
}
}
}
DEMO
You might find it easier to understand code written in a functional style. This is one solution, which I'll explain:
Object.values(formmd.formattr)
.map(obj => Object.values(obj))
.reduce((acc, vals) => acc.concat(vals), [])
The first expression Object.values(formmd.formattr) gives you an array of all the values (not keys) under formmd.formattr. Something like:
[{"LoginName": "A#test.com", "Password": "password", …}, {"AddressLine1": "201 MOUNT Road", "AddressLine2": null, …}, …]
Since you want the values within each of these sub-objects the next line .map(obj => Object.values(obj)) will do just that. It returns a new array where each object in the input array is transformed through Object.values(…). It returns something like:
[["A#test.com", "password", "", false], ["201 MOUNT Road", null, "1", …], …]
This array has all the data you're after, but in nested arrays, so it needs to be flattened with .reduce((acc, vals) => acc.concat(vals), []). This reduce will successively concat these sub-arrays to produce a single array like:
["A#test.com", "password", "", false, "201 MOUNT Road", null, "1", …]
which contains all the values of the child objects under formattr.
Here's some other ways to do it:
Object.values(formmd.formattr)
.reduce((acc, x) => acc.concat(Object.values(x)), [])
or
[].concat(...
Object.values(formmd.formattr)
.map(obj => Object.values(obj)))
You will have to use Object.entries()
The Object.entries() method returns an array of a given object's own
enumerable string-keyed property [key, value] pairs, in the same order
as that provided by a for...in loop. (The only important difference is
that a for...in loop enumerates properties in the prototype chain as
well).
Example -
for (const [key, value] of Object.entries(objectName)) {
console.log(`${key}: ${value}`);
}
Code Snippet -
var formmd = {
"frmType": "Registration",
"frmStage": "step1-complete",
"formattr": {
"SystemUser": {
"LoginName": "A#test.com",
"Password": "password",
"PIN": "",
"IsTestUser": false
},
"ConsumerAddress": {
"AddressLine1": "201 MOUNT Road",
"AddressLine2": null,
"AddressTypeId": "1",
"City": "OLA TRAP",
"State": "NM",
"Zipcode": "60005"
},
"ConsumerPhone": {
"PhoneTypeId": 6,
"PhoneNumber": "9876543210",
"PrimaryPhoneIndicator": null,
"AllowVoicemail": false
},
"PhysicianSpecialty": {
"SpecialtyList": [
"1",
"2"
]
},
}
}
for (const [key, value] of Object.entries(formmd.formattr)) {
console.log('Value',value);
}

Categories

Resources