I am iterating over this in my html file to create a dynamic table header.
I have a nested object
$scope.tasks = [{ "Number": 159232, "Title": "BUG", "Status": "pending", "Link": "www.google.com", "Card": "www.kanban.com", "Point": { "Value": 1, "IsTimeBased": true }, "ApprovalStatus":{ "CR": true , "BA": true } };
$scope.titles = Object.keys($scope.tasks[0]);
This iterates through all the non nested items but I cant figure out how to add the keys from the nested object.
I tried
$scope.titles.push(Object.keys($scope.tasks.ApprovalStatus[0]));
But nothing seems to be working I tried a splice in this fashion as well.
Instead of using .push use .concat.
$scope.titles = $scope.titles.concat(Object.keys($scope.tasks.ApprovalStatus[0]));
You can also do the concat for multiple args simultaneously.
Related
I want to take items from this array (the way I save things on the client)
[
{
"id": "-Mdawqllf_-BaW63gMMM",
"text": "Finish the backend[1]",
"status": true,
"time": 1625248047800
},
{
"id": "-Mdawqllf_-BaW63gGHf",
"text": "Finish the middle-end[2]",
"status": false,
"time": 1625248040000
},
{
"id": "-Mdawqllf_-BaW63gGHd",
"text": "Finish the front-end[3]",
"status": false,
"time": 1625248040000
}
]
And turn them into this format for how I save it server side
{ "todos": {
"-Mdawqllf_-BaW63gMMM": {
"text": "Finish the backend[1]",
"status": true,
"time": 1625248047800,
},
"-Mdawqllf_-BaW63gGHf": {
"text": "Finish the middle-end[2]",
"status": false,
"time": 1625248040000,
},
"-Mdawqllf_-BaW63gGHd": {
"text": "Finish the front-end[3]",
"status": false,
"time": 1625248040000,
}
},
}
Basically i turn items into an array on the client to help with sorting and making use of arrays. But before sending it back need to put into the right format
Use .map() to loop over the array of objects to exctract the id property, so you can use it as the key of the new object.
Use Object.fromEntries() to create the new object from the array returned by .map().
const data = [
{
"id": "-Mdawqllf_-BaW63gMMM",
"text": "Finish the backend[1]",
"status": true,
"time": 1625248047800
},
{
"id": "-Mdawqllf_-BaW63gGHf",
"text": "Finish the middle-end[2]",
"status": false,
"time": 1625248040000
},
{
"id": "-Mdawqllf_-BaW63gGHd",
"text": "Finish the front-end[3]",
"status": false,
"time": 1625248040000
}
];
const todos = {
Todos: Object.fromEntries(data.map(obj => [obj.id, obj]))
};
console.log(todos);
#Barmar's solutions is nice.
For the sake of learning or others googling. You can also reduce the array to an object.
const todos = data.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
const items = {
todos: {
...data
}
};
Assume that data is the array of objects.
Use the spread operator to copy all the array objects from data array to the todos object at key todos.
One important thing to note that you can't assign more than one objects without array to a single object key. You definately have to use the array to maintain all the objects under the one key.
Avoid using the hardcode index. Always use the spread operator
I am trying to read tags from a selected collection of bibliographic data in ZOTERO with Javascript.
For those who aren't familiar with ZOTERO: it has an in-built "run JS" panel to work directly with items selected / marked in the standalone version.
This is the script I am using to read data from a selected folder and access the tags:
var s = new Zotero.Search();
s.libraryID = ZoteroPane.getSelectedLibraryID();
var itemIDs = await s.search();
for (itemID of itemIDs) {
item = Zotero.Items.get(itemID);
return item;
itemTAG = item.getTags();
return itemTAG;
}
When I call return itemIDs; before the for loop, I get 4943 key:value pairs, which correctly mirrors the number of items in my collection.
The structure looks like this:
[
"0": 21848
"1": 21849
"2": 21850
"3": 21851
"4": 21852
"5": 21853
"6": 21854
"7": 21855
"8": 21856
"9": 21857
"10": 21858
]
What I would actually like to do is iterate through all IDs to get the bibliographic data for each item and return the tags.
This is why I first tried a for/in loop, but this didn't work, supposedly because I wasn't calling the key:value pairs (corresponding to a dictionary in Python?) correctly.
However, the above for/of loop works at least for the first item (item "0") and returns the following data:
{
"key": "BDSIJ5P4",
"version": 1085,
"itemType": "book",
"place": "[Augsburg]",
"publisher": "[Gabriel Bodenehr]",
"date": "[circa 1730]",
"title": "Constantinopel",
"numPages": "1 Karte",
"creators": [
{
"firstName": "Gabriel",
"lastName": "Bodenehr",
"creatorType": "author"
}
],
"tags": [
{
"tag": "Europa"
}
],
"collections": [
"DUW2PJDP"
],
"relations": {
"dc:replaces": [
"http://zotero.org/groups/2289797/items/ZB5J5VZK"
]
},
"dateAdded": "2019-02-13T17:27:29Z",
"dateModified": "2020-03-23T13:13:13Z"
}
So my two questions are:
How can I create a proper for/in loop that retrieves these same data for each item?
How can I return tags only? It seems that item.getTags() [which I used in analogy to the getNotes() examples in the documentation] may not be a valid function. Would that be specific to Zotero or Javascript in general?
Use map() to call a function on every array element and return an array of all the results.
return itemIDs.map(itemID => Zotero.Items.get(itemID).getTags())
I have 2 javascript arrays with below content:
Array1:
[{"key":"Agents"},{"key":"Formal"},{"key":"Annotation"},{"key":"Business"}]
Array2:
[
{"key":"Agents","class":"newclass","text":"Agents"},
{"key":"Business","class":"newclass1","text":"Business"},
{"key":"Formal","class":"newclass2","text":"Formal"},
{"key":"Annotation","class":"class5","text":"Annotation"},
{"key":"Rate","class":"newclass1","text":"Rates"}
]
The keys in both arrays are same. I am looking to update the array1 with the class and text values from array2 by matching keys.
Is there a way to do it without iterating both the arrays? This is just a small subset of the array. the actual can be a little larger.
Unfortunately, you would need to iterate through both arrays in order to find the right object in each array. Even using built in js prototype methods you would be iterating through the array.
One way you could solve this is my modifying your data structure. Instead of using an array of dictionaries, make a dictionary of dictionaries like so:
First Array:
{
"Agents": {},
"Business": {},
"Formal": {},
"Annotation": {},
"Rate": {}
}
Second Array:
{
"Agents": {
"class": "newclass",
"text": "Agents"
},
"Business": {
"class": "newclass1",
"text": "Business"
},
"Formal": {
"class": "newclass2",
"text": "Formal"
},
"Annotation": {
"class": "newclass5",
"text": "Annotation"
},
"Rate": {
"class": "newclass1",
"text": "Rates"
}
}
Now you can do something like Array1["Agents"] = Array2["Agents"] or however you want to add the data.
You could copy the properties across if you require new objects but it looks like array one is just a filter set of array two - you could simply map the first to every corresponding second. Iterating through both arrays can't be avoided but you can always create a map / ID cache so that you only make a single pass over each.
const arr1 = [
{"key": "Agents"},
{"key": "Formal"},
{"key": "Annotation"},
{"key": "Business"}
]
const arr2 = [
{"key": "Agents", "class": "newclass", "text": "Agents"},
{"key": "Business", "class": "newclass1", "text": "Business"},
{"key": "Formal", "class": "newclass2", "text": "Formal"},
{"key": "Annotation", "class": "class5", "text": "Annotation"},
{"key": "Rate", "class": "newclass1", "text": "Rates"}
]
const transformer = from => {
const cache = from.reduce((map, item) => (
map[item.key] = item, map
), {})
return ({ key }) => cache[key]
}
console.log(
arr1.map(transformer(arr2))
)
For a Chrome app, wich stores data in IndexedDB, i have a object like this:
var simplifiedOrderObject = {
"ordernumber": "123-12345-234",
"name": "Mr. Sample",
"address": "Foostreet 12, 12345 Bar York",
"orderitems": [
{
"item": "brush",
"price": "2.00"
},
{
"item": "phone",
"price": "30.90"
}
],
"parcels": [
{
"service": "DHL",
"track": "12345"
},
{
"service": "UPS",
"track": "3254231514"
}
]
}
If i store the hole object in an objectStore, can i use an index for "track", which can be contained multiple times in each order object?
Or is it needed or possibly better/faster to split each object into multiple objectStores like know from relational DBs:
order
orderitem
parcel
The solution should also work in a fast way with 100.000 or more objects stored.
Answering my own question: I have made some tests now. It looks like it is not possible to do this with that object in only 1 objectStore.
An other example object which would work:
var myObject = {
"ordernumber": "123-12345-234",
"name": "Mr. Sample",
"shipping": {"method": "letter",
"company": "Deutsche Post AG" }
}
Creating an index will be done by:
objectStore.createIndex(objectIndexName, objectKeypath, optionalObjectParameters);
With setting objectKeypath it is possible to address a value in the main object like "name":
objectStore.createIndex("name", "name", {unique: false});
It would also be possible to address a value form a subobject of an object like "shipping.method":
objectStore.createIndex("shipping", "shipping.method", {unique: false});
BUT it is not possible to address values like the ones of "track", which are contained in objects, stored in an array. Even something like "parcels[0].track" to get the first value as index does not work.
Anyhow, it would be possible to index all simple elements of an array (but not objects).
So the following more simple structure would allow to create an index entry for each parcelnumber in the array "trackingNumbers":
var simplifiedOrderObject = {
"ordernumber": "123-12345-234",
"name": "Mr. Sample",
"address": "Foostreet 12, 12345 Bar York",
"orderitems": [
{
"item": "brush",
"price": "2.00"
},
{
"item": "phone",
"price": "30.90"
}
],
"trackingNumbers": ["12345", "3254231514"]
}
when creating the index with multiEntry set to true:
objectStore.createIndex("tracking", "trackingNumbers", {unique: false, multiEntry: true});
Anyhow, the missing of the possibility to index object values in arrays, makes using indexedDB really unneeded complicated. It's a failure in design. This forces the developer to do things like in relational DBs, while lacking all the possibilities of SQL. Really bad :(
I want to create a array structure with child entities like this ->
$scope.groups = [
{
"categories": [
{
"name": "PR",
"sortOrder": 0,
"type": "category"
}
],
"name": "DEPT 1",
"sortOrder": 0,
"type": "group",
"id": "-JY_1unVDQ5XKTK87DjN",
"editing": false
}
];
from an array that dosen't have child entities but all the items are listed in one object like this->
$scope.groups = [
{
"name": "PR",
"sortOrder": 0,
"type": "category"
},
{
"name": "AD",
"sortOrder": 3,
"type": "category"
},
{
"name": "DEPT 2",
"sortOrder": 1,
"type": "group",
"id": "-JYZomQKCVseJmaZoIF9",
"editing": false,
"categories": []
},
];
Is there any possible way?
As #Eagle1 has rightly pointed out. You need to define your data model properly to define a function that does that grouping for you. That said, from what I understand you have a $scope.groups array of objects for a specific department containing some categories which you need to consolidate as a child element.
You could start by defining a function that returns an object like you mention:
var organize = function(arr){
cats = [];
dep = {};
$.each( arr, function( i, val ) {
if(val.type == "category")
cats.push(val);
else
dep = val;
});
dep.categories = cats;
return dep;
}
Ultimately, you'll have to traverse the array and look for objects of type category and dump them in an array and have that array as the categories key of the object that you intend to return. I hope it gets you started in the right direction.
of course it is.
It's doable in javascipt although to help you devise something we would need a relationship between categories.
However, that's sounds like something that should be done in your data model (a relationship between dept - category, classic reflexive relationship parent - children). angular should be receiving from the back end an array already ordered.