Convert object to array in Javascript / React - javascript

Using REST, I am retrieving an object(JSON format) which is to be converted to an array so that it can be inserted into a table.
This is done in the rendering function of React.
The input is updated every N minutes from the back-end.
How do I convert an object to an array?
I need only the values, not the keys, since the keys are already present as column values beforehand in the table itself.

You can use Object#values (ECMAScript 2017), but it's not supported by IE (see browser's compatibility).
Note: The ECMAScript 6 specification defines in which order the properties of an object should be traversed. This blog post explains the details.
const map = { a: 1, b: 2, c: 3 };
const result = Object.values(map);
console.log(result);
If you need to support IE, you can use Object#keys with Array#map:
const map = { a: 1, b: 2, c: 3 };
const result = Object.keys(map).map((key) => map[key]);
console.log(result);

I am not sure by map you mean the Map object or an ordinary JS object. However, just for variety I would like to mention that the Map objects are mostly (probably always) stringified like JSON.stringify([...myMap]). So if you happen to receive a Map object in JSON data may be you should do something like;
var myMap = new Map().set(1,"hey").set(2,"you"),
mapData = JSON.stringify([...myMap]),
values = JSON.parse(mapData).map(d => d[1]);
console.log("mapData:",mapData);
console.log("values:",values);

You can set initial value as array firstly. See this example:
const [conversations, setConversations] = useState([]); // fianal data is array
useEffect(() => {
const fetchConversations = async () => {
const res = await axios.get("/conversations/" + user._id);
setConversations(res.data);
};
fetchConversations();
}, [user._id]);
res.data convert to array by using useState([]) as initial value and convert to object by using useState({}).
And
return(
{conversations.map((conv) => (
))}
)

You can set initial value as array firstly. See this example:
const [conversations, setConversations] = useState([]); // fianal data is array
useEffect(() => {
const fetchConversations = async () => {
const res = await axios.get("/conversations/" + user._id);
setConversations(res.data);
};
fetchConversations();
}, [user._id]);
res.data convert to array by using useState([]) as initial value and convert to object by using useState({}).
And map this array:
return (
<>
{conversations.map((conv) =>
(<Conversations key={conv._id} conversation={conv} />))}
</>
)

Related

JavaScript - Creating Object with specific format out of 2 Arrays

I have 2 Arrays.
The Array "people" just holds basic information of some people.
The Array "subscriptions" has a lot of different subscriptions to games.
I want to have have an Array, where I can sort of have an Overview of what game subscriptions each person has. This is not real code I use, I am just trying to get used to JavaScript.
an example Element of an Array called people:
{"number":4251,"name":"Alex","surname":"Scott"}
an example Element of an Array called subscriptions:
{"number":4329,game:"Tetris"}
I want to make a new new Array with the following format:
person: (people[i]), subscriptions: [(subscriptions[j], subscriptions[j+k], ...)]
What I tried:
const array3 = people.map(x => {"person": x , "subscriptions": subscriptions.filter(y => y.number === x.number)});
It get this Error:
SyntaxError: Unexpected token :
How can I insert multiple key value pairs in in these Objects?
This happens because your argument in the map is interperting the { as opening bracket of the method body.
const arr = [{some: 1, object: 2}, {some:3, object:4}]
arr.map((o) => {original: o, cool: 'yes'})
To resolve this you have to explicitly return the object or add additional parenthesis to let the interperter know that this is not the method body:
const arr = [{some: 1, object: 2}, {some:3, object:4}]
const mapped = arr.map((o) => {return {original: o, cool: 'yes'}})
console.log(mapped)
const arr = [{some: 1, object: 2}, {some:3, object:4}]
const mapped = arr.map((o) => ({original: o, cool: 'yes'}))
console.log(mapped)
I hope this helps!
In your original code there is a syntax error, when it comes to the mapping part. Either you go with the long version of this command or, since you directly want to return the element, you can use the short version:
const people = [{"number":4251,"name":"Alex","surname":"Scott"}, {"number": 4329, "name":"Mr", "surname": "Tetri"}]
const subscriptions = [{"number":4329,game:"Tetris"}, {"number":4329, game:"Solitaire"}, {number: 4251, game: "Tetris"}]
// using an anonymous function including full body
const arrayLongVersion = people.map(x => { return {"person": x , "subscriptions": subscriptions.filter(y => y.number === x.number)} });
// using an anonymous function with direct return of elements
const arrayShortVersion = people.map(x => ({person: x , subscriptions: subscriptions.filter(y => y.number === x.number)}))
Here you go
const people = [
{"number":1,"name":"Alex","surname":"Scott"},
{"number":2,"name":"John","surname":"Anderson"},
{"number":3,"name":"Jacob","surname":"Sanderson"},
{"number":4,"name":"Lionel","surname":"Messi"},
{"number":5,"name":"Cristiano","surname":"Ronaldo"}
];
const subscriptions = [
{"number":1,game:"Tetris"},
{"number":2,game:"Super Mario"},
{"number":3,game:"Fortnite"},
{"number":4,game:"FIFA"},
{"number":5,game:"Zelda"}
];
const peopleSubscriptions = people.map(person => {
return {
...person,
subscriptions: subscriptions.filter(sub => sub.number === person.number)
}
});
console.log(peopleSubscriptions);

Convert incoming string to dictionary/map javascript

I am new javascript. I could do this in 2 seconds in python/java but I am struggling here. I am developing an reactJS app. I am retrieving a string which is a dictionary/HashMap<String, ArrayList> from a server via axios. I get response.data and my data is in the form:
{ "key1": [1,23,4,5,5,2],
"key2": [2,6,5,5,5,6,5],
...
}
I want to convert this into a map/dictionary so I can access it like so (get(), keys(), etc.
However, i am having trouble doing this.
console.log(typeof data) gives me string.
And when I JSON.parse() or JSON.stringify() and use new Map() i get this weird thing with thousands of integer keys and it doesn't act like I want. Any idea on how I can do this?
Thanks!
EDIT
Here is a more complete code example.
const fetchData = () => {
const url = "http://127.0.0.1:8081/pdata";
const promise = axios.get(url);
console.log(promise);
const dataPromise = promise.then((response) => response.data);
console.log(dataPromise);
return dataPromise;
}
export default function Home() {
//Bind the data to a useState Hook in React, to ensure that we have the correct data
const [data, setData] = React.useState([]);
//This function runs on page reload, twice. Your fetch data function will run repeatedly while contained
//within this functional component.
useEffect(() => {
fetchData().then((apiEndpoint) => {
//setting data equal to the result of the FetchData function
setData(apiEndpoint);
}).catch(err => console.log(err))
}, [])
// We now have the data.
// Convert it to a map
const map = new Map(Object.entries(data));
console.log(map.get("Model Used"));
console.log([...map.keys()]);
At point We now have the data, console.log(data) prints the incoming data correctly its just is of type string not map or whatever javascript calls it.
Using Map and Object#entries:
const obj = { "key1": [1,23,4,5,5,2], "key2": [2,6,5,5,5,6,5] };
const map = new Map(Object.entries(obj));
console.log(map.get("key1"));
console.log([...map.keys()]);
From https://flexiple.com/javascript/javascript-dictionary/
Are there dictionaries in JavaScript? No, as of now JavaScript does not include a native “Dictionary” data type. However, Objects in JavaScript are quite flexible and can be used to create key-value pairs. These objects are quite similar to dictionaries and work alike.
It seems you can just parse the string that you obtained to JSON and use the parsed object obtained. For example:
var api_response = `
{
"key1": [1,23,4,5,5,2],
"key2": [2,6,5,5,5,6,5]
}`;
var parsed_data = JSON.parse(api_response);
console.log(Object.keys(parsed_data))
console.log(parsed_data["key2"])
console.log(parsed_data.key1)

Unwanted modification in State variable (Hook), due to manipulation of local variable

import React, { useState, useEffect } from "react";
export const Test = () => {
const [data, setData] = useState([]);
const file = [{ id: 1, description: "Test Data" }];
useEffect(() => setData(file), []);
const manipulateData = (data) => {
let tempArray = [...data];
tempArray.map((item) => delete item.id);
};
return (
<>
<h1>Testing Data</h1>
{manipulateData(data)}
{console.log(data)}
</>
);
};
I want to make modification to the local variable "tempArray", and the changes shall not reflect in the variable "data"
This happens because you are creating a new array, but the objects in that array are not deeply copied. Instead, they represent just a reference to the very same objects as in data.
Because both references are pointing at the same object, if you delete an object property from the tempArray objects, you are actually deleting it from the data objects.
If you want to solve this, you have to destroy the reference by making a deep copy of the objects from the data array.
Here is an example how to do it:
export const Test = () => {
const [data, setData] = useState([{ id: 1, description: "Test Data" }]);
const manipulateData = (data) => {
let tempArray = data.map((item) => {item.description}); //this will create an array with new object, and destroy the reference to the objects of data.
};
return (
<>
<h1>Testing Data</h1>
{manipulateData(data)}
{console.log(data)}
</>
);
};
Also, instead of deleting a property, better pick the one that you need.
The following code:
let tempArray = [...data];
only shallow copies your data array, meaning that any of the objects inside of tempArray refer to the same objects in memory that are within the data array. This means that when you loop over your objects with .map(), each item refers to an object from data as well, which results in the objects in data changing when you use delete item.id.
Currently, you are using .map() just to loop over your tempArray, this isn't the purpose of .map(). The .map() method returns a new array, and the callback function you pass it should return a new value that you want to map the current value to. This means you can use .map() to create tempArray, by making the callback function return a new object that excludes the id property:
const manipulateData = (data) => {
const tempArray = data.map(({id, ...rest}) => rest);
// ... do what you need with `tempArray` ...
};
Above, {id, ...rest} is destructuring assignment syntax, which extracts the id property from the current element, and stores all other properties/values from the current object in rest. This allows you to create a new object that excludes the id property.
As a side note, you shouldn't be calling methods such as console.log() and manipulateData() inside of JSX if they don't return anything meaningful that will be rendered to the screen, instead, you can put these in a useEffect() hook.
const [data, setData] = useState([{ id: 1, description: "Test Data" }]);
try this
Your way is right in case you are not using a multi-dimensional array, but here you are cloning a multi-dimensional array,
and by using the = operator, it’ll assign objects/arrays by reference instead of by value! That means whenever you modify any of the two objects it's going to affect the value in both.
A good way to solve this is by creating a deep clone by doing something like this
const tempArray = JSON.parse(JSON.stringify([...data]))
tempArray.map((item) => delete item.id)

Not able to set state as array of objects inside map function

I am getting data from word press API then I structure the data inside the map function. I am not able to set state as array of objects inside map function I
get Arrays of different objects or Objects of different objects but not a single
Array of Objects
const rsp = response.data;
const map = rsp && rsp.map(item => {
let struct = {};
let data = [];
const id = item.id;
const title = item.title['rendered'];
const image = item['_embedded']['wp:featuredmedia'][0].source_url;
const banner = item.ACF.banner_image.url;
const products = item.ACF.celebrity_products;
let store={
id:id,
title:title,
image:image,
banner:banner,
products:products
};
setRes(prevState => {
// struct['data'] =store;
// data.push(store);
return{ ...prevState,
id: store.id,
name: store.title,
uri: store.image,
banner: store.banner,
products: store.products
}})
});
I think you'd want more something like :
const [items, setItems] = useState([])
rsp && setItems(rsp.map(item => ({
id: item.id,
name: item.title['rendered'],
uri: item['_embedded']['wp:featuredmedia'][0].source_url,
banner: item.ACF.banner_image.url,
products: item.ACF.celebrity_products
})))
I think you didn't provide the complete story of you code. but I think we can help.
if you intend to have the result of your processing as an array inside the map variable then you should've returned something inside it like
let oddNumber = [ 1, 3, 5 ];
const map = oddNumber.map( oneOddNumber => { return oneOddNumber * 2; } );
// now map is [ 2, 6, 10 ]
or if you intend to save the array you want using setRes function then you should've done something like
setRes(prevState => ({
...prevState,
theResultArray: [...prevState.theResultArray, { id: store.id, ..... } ]
}))
and now you state have the property name theResultArray which is an array of object which you've iterated on.
hope you can provide more complete code so help can be more clear next time :D

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