I'm having trouble getting a specific set of values from an array of arrays because the values come up as aundefineda. my array is stored in state and set up like this:
survey: [{names: ["sara", "tom"]}, {age: ["17", "33"]}, {col: ["blue", "green"]}]
To access just the names, I've been trying to use the line:
console.log(this.state.survey.names)
When I check, the console has "undefined" for the names. When I check the value of survey, it shows up as an array of arrays, where each nested array has two values stored inside.
I want to check this because I am trying to map out the nested arrays and mapping out Survey names isn't working because the length shows 0. I am successful in mapping out nested arrays when they are not stored in state, so I am wondering what I am missing or if my syntax is incorrect.
You're trying to access an array as if it was an object, instead of an array of objects. A simple fix is -
this.state.survey.find(item => item.names).names
In the long term, unless you have a reason to store this as an array, it would be a lot easier to reorganize and store as objects. If you restructure this to be something like
survey: {
names: ['name1', 'name2'],
age: ...etc
If you are trying to say that Sara is 17 and her col is blue, why not just store that as a single object?
Related
I'm using OpenRefine to pull in information on publisher policies using the Sherpa Romeo API (Sherpa Romeo is a site that aggregates publisher policies). I've got that.
Now I need to parse the returned JSON so that those with certain pieces of information remain. The results I'm interested in need to include the following:
'any_website',
'any_repository',
'institutional_repository',
'non_commercial_institutional_repository',
'non_commercial_repository'
These pieces on information all fall under an array called "permitted_oa". For some reason, I can't even work out how to just pull out that array. I've tried writing grel expressions such as
value.parseJson().items.permitted_oa
but it never reutrns anything.
I wish I could share the JSON but it's too big.
I can see a couple of issues here.
Firstly the Sherpa API response items is an array (i.e. a list of things). When you have an array in the JSON, you either have to select a particular item from the array, or you have to explicitly work through the list of things in the array (aka iterate across the array) in your GREL. If you've previously worked with arrays in GREL you'll be familiar with this, but if you haven't
value.parseJson().items[0] -> first item in the array
value.parseJson().items[1] -> second item in the array
value.parseJson().items[2] -> third item in the array etc. etc.
If you know there is only ever going to be a single item in the array then you can safely use value.parseJson().items[0]
However, if you don't know how many items will be in the array and you are interested in them all, you will have to iterate over the array using a GREL control such as "forEach":
forEach(value.parseJson().items, v, v)
is a way of iterating over the array - each time the GREL finds an item in the array, it will assign it to a variable "v" and then you can do a further operation on that value using "v" as you would usually use "value" (see https://docs.openrefine.org/manual/grel#foreache1-v-e2 for an example of using forEach on an array)
Another possibility is to use join on the array. This will join all the things in an array into a string.
value.parseJson().items.join("|")
It looks like the Sherpa JSON uses Arrays liberally so you may find more arrays you have to deal with to get to the values you want.
Secondly, in the JSON you pasted "oa_permitted" isn't directly in the "item" but in another array called "publisher_policy" - so you'll need to navigate that as well. So:
value.parseJson().items[0].publisher_policy[0].permitted_oa[0]
would get you the first permitted_oa object in the first publisher_policy in the first item in the items array. If you wanted to (for example) get a list of locations from the JSON you have pasted you could use:
value.parseJson().items[0].publisher_policy[0].permitted_oa[0].location.location.join("|")
Which will give you a pipe ("|") separated list of locations based on the assumption there is only a single item, single publisher_policy and singe permitted_oa - which is true in the case of the JSON you've supplied here (but might not always be true)
I'm using React Native and Open Weather Map API to build a small weather app. The data I retrieve from the API call is more than I want to use so I parse out just the pieces I need and store them in an array. I then take the array and set it to a state object. I can reference the object, but instead of saying my array is an array, it says it's an object, and thus won't let me use any array methods on it. How do I get around this?
//reponseData is the data retrieved from the API call; the data retrieved is an object with arrays and objects
within. The forecast data for the next five days is given in 3 hour increments, so you have a 40 item array of
data pieces. I loop through this list of 40 items, pull out just what I need...
let forecastArray = [];
for (let i=0; i<responseData.list.length; i++) {
let day = responseData.list[i].date
let high = responseData.list[i].weather[0].hiTemp
let low = responseData.list[i].weather[0].loTemp
let condition = responseData.list[i].sys.condition
forecastArray.push(day)
forecastArray.push(high)
forecastArray.push(low)
forecastArray.push(condition)
this.setState({
forecastData: forecastArray
})
When I log, I get an array....
console.warn("forecast is: ", this.state.forecastData)
OUTPUTS: forecast is: ["11-06-2019", 52.5, 47.3, "sunny", "11-06-2019", 63.9, 39.7, "sunny", ...]
Referencing this.state.forecastData[2], for example, however was giving me errors. So I checked the typeof this.state.forecast to see why and it says the array is an Object? I need to further divide out the array data and manipulate it. The first several items (e.x. forecastData[0] through forecastData[9] would be for the forecasted weather for 11-06-2019 at 3pm, ,6pm, 9pm so I need to pull those items, get the highest high and lowest low, etc. I can't do that since I can't even reference the items in the array.
Things I've tried:
using Object.entries and Object.assign methods, but that just splits the items into several arrays, with the first item being the location number and the second item being the array item content. I've tried manipulating the array within the component that uses it, but it still is an Object not an Array, so I can't reference the individual items. The data set is large enough I don't think it would be best practice to push each of the 40+ items into their own state object key.
in Javascript array is a subset of object , i'e it has the same prototype. So typeof Array will be an object. Thats not an issue. Can you update with the error which you are getting while accessing this.state.forecastData[2] coz what i . believe its something not with syntax , rather with the duration of API call.
I would recommend when accessing this.state.forecastData[2] first check if its length is greater than 0 , that way you are sure that there is data inside the array.
constructor(props){
forecastData:[]
}
and when you use it ,
if(this.state.forecastData.length > 0){
this.state.forecastData[2]
}
Try this, and revert with doubts.
Thank you, Gaurav Roy! You were partly correct. The typeof didn't matter at all. But the issue wasn't with the duration of my API, it was that my component was trying to render when it didn't have the data from the API call yet! I put in a conditional
{this.state.forecast !== null && <Forecast forecast=this.state.forecastData />}
and got things working now. Thanks for the quick reply!
I am trying to append/remove items from an array inside of a Firestore Document but every time the entire array is replaced instead of the new value being appended. I have tried both of the following:
batch.setData(["favorites": [user.uid]], forDocument: bookRef, options: SetOptions.merge())
batch.updateData(["favorites": [user.uid]], forDocument: bookRef)
I know that instead of an array I can use an object/dictionary but that would mean storing additional data that is irrelevant (such as the key), all I need is the ID's stored inside the array. Is this something that is currently possible in Firestore?
Update elements in an array
If your document contains an array field, you can use arrayUnion() and arrayRemove() to add and remove elements. arrayUnion() adds elements to an array but only elements not already present. arrayRemove() removes all instances of each given element.
let washingtonRef = db.collection("cities").document("DC")
// Atomically add a new region to the "regions" array field.
washingtonRef.updateData([
"regions": FieldValue.arrayUnion(["greater_virginia"])
])
// Atomically remove a region from the "regions" array field.
washingtonRef.updateData([
"regions": FieldValue.arrayRemove(["east_coast"])
])
See documentation here
Actually, nowadays it is possible. With latest updates db.collection.updateData
method actually appends new item to array instead of replacing it.
Example usage can be found in Firebase documentation.
If you need to do it manually, you can use
FieldValue.arrayUnion([user.uid])
Nope. This isn't possible.
Arrays tend to be problematic in an environment like Cloud Firestore where many clients could theoretically append or remove elements from an array at the same time -- if instructions arrive in a slightly different order, you could end up with out-of-bounds errors, corrupted data, or just a really bad time. So you either need to use a dictionary (where you can specify individual keys) or replace the entire array.
I'm trying to retrieve Firebase data with Polymer Fire. When I look in the console it's returning two objects, however the length of the array is three. When I'm trying to execute a dom-repeat I'm successfully printing two filled in rows but also one empty row. How is this possible?
Firebase stores data as associative arrays, essentially a dictionary of key/value pairs.
That means that in order to deal with arrays, it converts an array to a dictionary when you store it and then back to an actual array when you read it. Here you are getting bitten by the SDK converting your non-array into an array by padding it with a leading element.
If you don't want the SDK to do this conversion, the easiest way is to store the items with a non-numeric key, e.g. "item1", "item2".
Read more about how Firebase deals with arrays in this classic blog post: https://firebase.googleblog.com/2014/04/best-practices-arrays-in-firebase.html
The question was difficult to put into words, but here is my situation. I have several Monster objects in an array called monsters. Each monster has a name property which is a String.
I have a second array called monsterNames, which contains several monster names (as Strings).
I want to be able to filter all the monster objects in monsters array based on whether the individual monster object's name property appears in the monsterNames array.
I have been looking at solutions so far I have only found solutions that filter based on a single condition, which allows me to only filter based on a single monster name in the monsterNames array. Can anybody help me find an efficient solution to this?
You could do something like:
let monsters: [Monster] = ...
let monsterNames: [String] = ...
let filteredMonsters = monsters.filter { monsterNames.contains($0.name) }
This doesn't perform all that well, since it will go over the names array up to n times for each monster, but if your names arrays is small, this won't be a problem.