Update nested array ES6, JavaScript - javascript

I have the following array of objects:
[{
idChatPublic: "1",
message: "hello",
chatLike: [{
id: "1",
idChatPublic: "1"
}]
}]
What I want is simply add a new object into chatLike array.
Here is my attempt, but it doesn't seem to be working whats wrong with this piece of code?
async function sendLike(messageId: string) {
const newLike = {
idChatPublic: messageId,
}
mutateMessages(
(data) => {
console.log(data) // returns the array I want to update
data.map((message) => {
if (message.idChatPublic === messageId) {
console.log(message.chatLike) // returns the array inside the object I want to update
return {
...message,
chatLike: [...message.chatLike, newLike]
}
} else {
return message
}
})
}
)
}

The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
Probably, you have to create const with new array and return it:
const newData = data.map((message) => {
if (message.idChatPublic === messageId) {
console.log(message.chatLike) // returns the array inside the object I want to update
return {
...message,
chatLike: [...message.chatLike, newLike]
}
} else {
return message
}
});
return newData;

const data = [
{
idChatPublic: "1",
message: "hello",
chatLike: [
{
id: "1",
idChatPublic: "1",
},
],
},
];
function updateChatLike() {
return data.map((d) => {
return {
...d,
chatLike: [
...d.chatLike,
{
id: 2,
idChatPublic: "2",
},
],
};
});
}
console.log(JSON.stringify(updateChatLike(), null, 4));
I have used JSON.stringify() to log complete nested object
Output
[
{
"idChatPublic": "1",
"message": "hello",
"chatLike": [
{
"id": "1",
"idChatPublic": "1"
},
{
"id": 2,
"idChatPublic": "2"
}
]
}
]

You don't need map(). I think you can do that like this:
async function sendLike(messageId: string) {
const newLike = {
idChatPublic: messageId,
};
mutateMessages((data) => {
data.forEach((message) => {
if (message.idChatPublic === messageId) {
message.chatLike.push(newLike);
}
}
});
}
Loop throw your objects array with forEach() and if the id will match you can update chatLike array with push() to add a new newLike object.

Map is not necessary here in your case.
Try this.
const data = [{
idChatPublic: "1",
message: "hello",
chatLike: [{
id: "1",
idChatPublic: "1"
}]
}];
console.log("before " , data);
sendLike(1);
console.log("after " , data);
function sendLike(messageId) {
const newLike = {
idChatPublic: messageId,
}
// mutateMessages((data) => {
data.forEach((message) => {
//console.log(message.idChatPublic);
if (message.idChatPublic == messageId) {
message.chatLike.push(newLike);
}
});
//});
}

Related

moving a key value pair out of an array

I am trying to move everything in the Array Results outside and into the original object
this is the object
{
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
It should look like this
{
"Name": "John",
"Type": "DB",
"Immediate_Action": "No",
}
What I have so far is this
const mapOscarResults = ({ data }) => {
return data.map(entry => {
let mapped = {...entry};
entry.Results.forEach(key => {
let Type = mapped[key.Type]
if (mapped[key]) {
mapped[key].push(entry.Results[key]);
} else {
mapped[key] = [entry.Results[key]];
}
});
return mapped;
});
};
You can simply spread the Results array into an Object.assign() call.
const input = { "Name": "John", "Results": [{ "Type": "DB", "Immediate_Action": "No", }, { "Another": "value" }] };
const { Results, ...refactored } = input;
Object.assign(refactored, ...Results);
console.log(refactored)
This code works for your example:
const { Results: results, ...rest } = {
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
const res = {...rest, ...results.reduce((prev, curr) => ({
...prev,
...curr
}), {})}
console.log(res)
But I don't know what you expect when the Results array has more than one element.
In that condition, if this code does not fill your needs, ask me to change it.
however, it will join first Result with index 0, you can expand it
const data = {
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
const mapOscarResults = (data) => {
for (let i in Object.keys(data)){
if (Array.isArray(data[Object.keys(data)[i]])){
newKey = data[Object.keys(data)[i]][0]
data = {... data, ...newKey}
delete data[Object.keys(data)[i]]
}
}
return data
};
console.log(mapOscarResults(data))

Loop through array of differently structured JSON objects/arrays

I feel like this is mostly an issue with how I'm looping through the JSON, so am posting that first. This is a series of JSON responses from Promise.allSettled() posted below.
The problem I am having is with the second "status" object between content and anoObject1 as I'm looping through the JSON responses. I've shown some console.logs() below that are successful
Here is the series of JSON responses:
[
{
"status": "fulfilled",
"value": {
"content": {
"object1": {
"kv": "Y",
"kv1": "1000",
"kv2": {
"okv": "A",
"okv1": "1"
},
"kw": "A"
}
},
"retrievalDate": "2022-05-04T23:01:57.710+0000"
}
},
{
"status": "fulfilled",
"value": {
"content": [
{
"anoObject1": {
"ano": "A",
"ano1": {
"ona": "B",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
},
{
"anoObject2": {
"ano": "B",
"ano1": {
"ona": "Y",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
}
],
"retrievalDate": "2022-05-04T23:01:57.707+0000"
}
}
]
Here are the async fetch calls:
export async function allCallouts(key, value){
const BASE_URL = 'https://baseurl.com/service/'
const API_KEY = 'apikey'
const endpoint1 = 'https://url1.com/a/';
const endpoint2 = 'https://url1.com/b/';
try{
const results = await Promise.allSettled(
[
fetch(endpoint1).then((response) => response.json()),
fetch(endpoint2).then((response) => response.json()),
]
)
return results
} catch (error){
console.log(error)
}
}
Here is the function I am calling the first function from
async handleFetchCallouts() {
returnedResults;
await allCallouts(key, value)
.then(results => {
this.returnedResults = results
}).catch(err => {
console.log('this is err: ' + err);
})
let arrayLength = this.returnedResults.length
for (var i = 0; i < arrayLength; i++) {
//I am able to console.log(this.returnedResults[i].value.content)
//it returns the response and number I am expecting
//but the structure of the JSON response (above) is tripping me up
if (this.returnedResults[i].value.content['object1'] != null) {
//I can console.log() this successfully
console.log(this.returnedResults[i].value.content['object1'].kv)
}
if (this.returnedResults[i].value.content['anoObject1'] != null) {
//having trouble getting to this object and looping through each
}
}
}
Thank you for any help! If you see other design flaws with my code or an easier way to do things, please suggest.
Create a recursive function and dont use any hardcoded key. Iterate through the content and check if value is an array using Array.isArray. If so then handle it in a different function and so for if value is of type object
const arrayLength = [{
"status": "fulfilled",
"value": {
"content": {
"object1": {
"kv": "Y",
"kv1": "1000",
"kv2": {
"okv": "A",
"okv1": "1"
},
"kw": "A"
}
},
"retrievalDate": "2022-05-04T23:01:57.710+0000"
}
},
{
"status": "fulfilled",
"value": {
"content": [{
"anoObject1": {
"ano": "A",
"ano1": {
"ona": "B",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
},
{
"anoObject1": {
"ano": "B",
"ano1": {
"ona": "Y",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
}
],
"retrievalDate": "2022-05-04T23:01:57.707+0000"
}
}
]
for (let i = 0; i < arrayLength.length; i++) {
const content = arrayLength[i].value.content;
// checking if value is of type array or object
if (Array.isArray(content)) {
handleContentArray(content)
} else if (content && typeof(content) === 'object') {
handleContentObject(content)
}
}
function handleContentArray(contentArray) {
// iterate the array
contentArray.forEach(item => {
// if the content of the array is an object then call the function which handles the object
if (item && typeof item === 'object') {
handleContentObject(item)
}
})
}
function handleContentObject(contentObject) {
// iterate through the key
for (let keys in contentObject) {
// if the value of the key is an object then recursively call the same function
if (contentObject && typeof(contentObject[keys]) === 'object') {
return handleContentObject(contentObject[keys])
} else {
// log the key value pair
console.log(`KEY:- ${keys}, VALUE: - ${contentObject[keys]}`)
}
}
}
You can use Array.isArray() to ascertain if an object is an Array and customize how you handle the object accordingly.
// Same structure as in the question, but removed extraneous
// fields and compacted for the sake of brevity.
const input = `[
{"value":{"content":{"object1":{"kv":"Y"}}}},
{"value":{"content":[
{"anoObject1":{"ano":"A"}},
{"anoObject1":{"ano":"B"}}
]}}]`;
const result = JSON.parse(input);
for (const r of result) {
const content = r.value.content;
if (Array.isArray(content)) {
for (const c of content) {
console.log(`anoObject1.ano = ${c.anoObject1.ano}`);
}
} else {
console.log(`object1.kv = ${content.object1.kv}`);
}
}
For your second if statement in the for loop, you would have to iterate through all items under value.content. Replace the second if statement with this for a plug and play:
if (Array.isArray(this.returnedResults[i].value.content)) for (let i of this.returnedResults[i].value.content) {
}
Inside the new loop, i will be equivalent to
{
"anoObject1": {
"ano": "A",
"ano1": {
"ona": "B",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
}
The reason for this is that the second if statement was attempting to find a property/key of an array instead of each object in the array of objects.
I would also recommend reading up on the following to make your coding easier/better:
let
for...in/for...of
truthy/falsy

A function to obtain all leaf node properties of an object in an array of string in javascript

Request you to please help in building a function in javascript to obtain the mentioned output from the input given.
INPUT : An object (possibly a nested object)
example :
{
"message":"string" ,
"data1": {
"Output1": {
"leaf1": "abc",
"Leaf2": "123"
}
}
"data2": {
"Output2": {
"leaf3": "abc",
"leaf4": "123"
}
}
}
OUTPUT : An array of string
Example :
str= ["message", "data1.Output1.leaf1", "data1.Output1.leaf2" , "data2.Output2.leaf3","data2.Output2.leaf4"]
Something like this it will work
const getBranches = (data, prefix=[]) => {
if (typeof(data) !== 'object') {
return prefix.join('.')
}
return Object.entries(data).flatMap(([k, v]) => getBranches(v, [...prefix, k]))
}
const data = {
"message": "string",
"data1": {
"Output1": {
"leaf1": "abc",
"Leaf2": "123"
}
},
"data2": {
"Output2": {
"leaf3": "abc",
"leaf4": "123"
}
}
}
console.log(getBranches(data))
Second version
const data = {
"message": "string",
"data1": {
"Output1": {
"leaf1": [{
"b": {
"c": "12"
}
}]
}
},
"data2": {
"Output2": {
"leaf3": "abc",
"leaf4": "123"
}
}
}
const getBranches = (data, prefix = []) => {
if (typeof(data) !== 'object') {
return prefix.join('.')
}
return Object.entries(data).flatMap(([k, v]) => Array.isArray(data) ? getBranches(v, [...prefix]) : getBranches(v, [...prefix, k]))
}
console.log(getBranches(data))

Firestore bulk add field to array

I am struggling to add a field to an map in an array. I am trying to add "canAssist": false to each map in the array for each of the countries.
Here is my database:
[
{
"Afghanistan": {
"country": "Afghanistan",
"countryCode": "AF",
"countryCodeAlt": "AFG",
"emoji": "🇦🇫",
"packages": [
{
"name": "Luxury Couple",
"cost": "$2000.00",
// I want to add canAssist:false here!
},
{
"name": "Quick Retreat",
"cost": "$1000.00",
// I want to add canAssist:false here!
}
]
}
},
{...}
{...}
]
This is what I've tried:
let travelData = database.collection('countries').doc(docName);
travelData.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(array) {
packages.map(package => {
return package.add({
canAssist: false
});
})
});
});
You can use Object.values() and object destructuring to achieve this.
const querySnapshot = [
{
Afghanistan: {
country: 'Afghanistan',
countryCode: 'AF',
countryCodeAlt: 'AFG',
emoji: '🇦🇫',
packages: [
{
name: 'Luxury Couple',
cost: '$2000.00',
// I want to add canAssist:false here!
},
{
name: 'Quick Retreat',
cost: '$1000.00',
// I want to add canAssist:false here!
},
],
},
},
{
...
},
{
...
},
];
const updateSnapshot = (snapshot, newData) => {
return snapshot.map(countryData => {
// only one field with the name of the country
const country = Object.values(countryData)[0];
let updatedCountry = { ...country };
const field = country[newData.field];
if (field) {
if (typeof field === 'string') {
updatedCountry[newData.field] = newData.values;
} else if (Array.isArray(field)) {
updatedCountry[newData.field] = field.map(data => ({ ...data, ...newData.values }));
}
}
return { [updatedCountry.country]: updatedCountry };
});
};
(() => {
console.log('Original', JSON.stringify(querySnapshot, null, 4));
const updatedSnapshot = updateSnapshot(querySnapshot, { field: 'packages', values: { canAssist: false } });
console.log('Updated', JSON.stringify(updatedSnapshot, null, 4));
const updatedSnapshot2 = updateSnapshot(querySnapshot, { field: 'emoji', values: '🇪🇸' });
console.log('Spanish!', JSON.stringify(updatedSnapshot2, null, 4));
})();
Of course, you don't need to have that dynamism with the 'newData', I just added in case you want to play around any field of your datasource.

Trying to change/match JSON object

I figure I shouldn't be having trouble with this, but I am. I am trying to switch up the syntax/variables of a JSON object to match a certain parameters.
Here is the JSON I am working with:
{
"name":"BHPhotovideo",
"prices":[
{
"price":"799.00",
"createdAt":"2017-07-23T16:17:11.000Z",
"updatedAt":"2017-07-23T17:21:41.000Z"
},
{
"price":"770.00",
"createdAt":"2017-07-21T16:17:11.000Z",
"updatedAt":"2017-07-23T16:17:11.000Z"
},
{
"price":"599.00",
"createdAt":"2017-07-19T16:17:11.000Z",
"updatedAt":"2017-07-22T16:17:11.000Z"
},
{
"price":"920.00",
"createdAt":"2017-07-22T16:17:11.000Z",
"updatedAt":"2017-07-22T16:17:11.000Z"
}
]
},
etc...
I am just trying to get the data to be formatted like this:
{
"label":"BHPhotoVideo", // Same as name
"data":[
{
"x":"2017-07-23T16:17:11.000Z", // Same as createdAt
"y":799 // Same as price
},
{
"x":"2017-07-21T16:17:11.000Z",
"y":770
},
{
"x":"2017-07-19T16:17:11.000Z",
"y":599
},
{
"x":"2017-07-22T16:17:11.000Z",
"y":920
}
]
},
etc...
The amount of these objects are dynamic/subject to change, I've been making a mess out of foreach loops and trying to piece this together. I keep coming into errors, what's the best way to approach this?
What about this ?
data.map(
(item) => ({
"label":"BHPhotoVideo", // Same as name
"data": item.prices.map(nested => ( {
"x":nested.createdAt,
"y":nested.price
}))
})
)
Did you want the y values to be integers?
var ar = [
{
"name":"BHPhotovideo",
"prices":[
{
"price":"799.00",
"createdAt":"2017-07-23T16:17:11.000Z",
"updatedAt":"2017-07-23T17:21:41.000Z"
},
{
"price":"770.00",
"createdAt":"2017-07-21T16:17:11.000Z",
"updatedAt":"2017-07-23T16:17:11.000Z"
},
{
"price":"599.00",
"createdAt":"2017-07-19T16:17:11.000Z",
"updatedAt":"2017-07-22T16:17:11.000Z"
},
{
"price":"920.00",
"createdAt":"2017-07-22T16:17:11.000Z",
"updatedAt":"2017-07-22T16:17:11.000Z"
}
]
},
{
"name":"Adorama",
"prices":[
{
"price":"799.00",
"createdAt":"2017-07-22T16:17:11.000Z",
"updatedAt":"2017-07-23T17:21:41.000Z"
},
{
"price":"799.00",
"createdAt":"2017-07-20T16:17:11.000Z",
"updatedAt":"2017-07-23T16:17:11.000Z"
},
{
"price":"810.00",
"createdAt":"2017-07-18T16:17:11.000Z",
"updatedAt":"2017-07-22T16:17:11.000Z"
},
{
"price":"799.00",
"createdAt":"2017-07-17T16:17:11.000Z",
"updatedAt":"2017-07-22T16:17:11.000Z"
}
]
}
];
var out = ar.map( function(a) {
return {
"label" : a.name,
"prices" : a.prices.map( function(aa) { return {x: aa.createdAt, y: aa.price} })
}
});
console.log( out );
map over the original array returning a changed object; returning the name, and a new array from using map over the prices.
const obj2 = obj.map((item) => {
return {
label: item.name,
data: item.prices.map((data) => {
return {
x: data.createdAt,
y: data.price
}
})
}
});
DEMO

Categories