I want to create a for loop that will generate a new element for sampleItems based on a fixed number set in a for loop.
var list = new WinJS.Binding.List();
var groupedItems = list.createGrouped(
function groupKeySelector(item) { return item.group.key; },
function groupDataSelector(item) { return item.group; }
);
generateSampleData().forEach(function (item) {
list.push(item);
});
function generateSampleData() {
var sampleGroups = [
{ key: "group1", title: "Event1", backgroundImage: "/images/event1.jpg"}
];
var sampleItems = [
{ group: sampleGroups[0], title: "Item Title: 1", content: "http://192.168.201.41/Stream" + [i] + ".mp4", backgroundImage: "/images/image1.jpg" }
];
return sampleItems;
}
I tried to place a for loop within sampleItems but i'm not allowed place the loop there.
As per conversation in question comments, here is the basic array population code for js:
var streams = 7;
var sampleItems = [];
for(i = 0; i < streams; i++) {
sampleItems.push({'a': 'b', 'c': 'd'})
}
Replace {'a': 'b', 'c': 'd'} with desired key-value pairs
Well you are looping over an array containing one object as entry. what you probably want to do is to discard you object structure completely and just use an simple array like:
var sampleItems = [ sampleGroups[0], "Item Title: 1", ..... ];
you could also make it a an actual object without using arrays but it seems to me that you want to use the List. If no List ist necessary just put the whole object genereated by
generateSampleData into you object or append it to an existing object.
Related
I am creating a function which uses an array to navigate through a JSON object, pushing its keys to a results array at each step. The trouble is, I can't get the loop to use the updated object with each successive loop.
JSON object:
myData = {
'Eye': {
'Abnormal Morphology': [
'Neoplasm',
'Abnormality of the globe'
],
'Abnormal Physiology': [
'Hemorrhage',
'Ptosis',
'Ocular pain'
]
},
'Ear': {
'Outer Ear': [
'Abnormality of the pinna',
'Abnormal location of ear',
'Extra chondra fold'
],
'Middle Ear': [
'Glue ear',
'Otitis media'
]
}
}
And the function:
view = ['Ear', 'Outer Ear']
getMenuItems(object, array) {
let menuItems = Object.keys(object);
let result = [menuItems];
for (let item in array) {
object = object[item]; // use updated object each time
menuItems = Object.keys(object);
result.push(menuItems);
}
return result;
}
The result I'm expecting is:
[['Eye', 'Ear'], ['Outer Ear', 'Inner Ear'], ['Abnormality of the pinna', 'Abnormal location of ear', 'Extra chondra fold']]
But all I get is:
['Eye', 'Ear']
for( let item in array )
Iterates over the items key (0,1,2). May use of instead to iterate over props:
for( const item of array )
Then it works
I am using Ionic with AngularJS and I am using a localForage database and AJAX via $http. My app has a news stream that contains data like this:
{
"feed":[
{
"id":"3",
"title":"Ein Hund",
"comments:"1"
},
{
"id":"2",
"title":"Eine Katze",
"comments":"2"
}
],
"ts":"20150907171943"
}
ts stands for Timestamp. My app saves the feed locally via localForage.
When the app starts it first loads the locally saved items:
$localForage.getItem("feed").then(function(val) { vm.feed = val; })
Then, it loads the new or updated items (ts < current timestamp) and merges both the old and new data:
angular.extend(vm.feed, response.data.feed);
Updated items look like this:
{
"feed":[
{
"id":"2",
"title":"Eine Katze",
"comments":"4"
}
],
"ts":"20150907171944"
}
That is, the comments count on feed item 2 has changed from 2 to 4. When I merge the old and new data, vm.feed has two items with id = 2.
Does angularjs has a built-in "merge by id" function, i. e. copy from source to destination (if it is a new element), or otherwise replace the old element? In case angularjs does not have such a function, what's the best way to implement this?
Thanks in advance!
angular.merge(vm.feed, response.data.feed);
// EDIT
Probably, it will not merge correctly, so you have to update all properties manually. Update ts property and then find your object with id and replace it.
There is no builtin, I usually write my own merge function:
(function(){
function itemsToArray(items) {
var result = [];
if (items) {
// items can be a Map, so don't use angular.forEach here
items.forEach(function(item) {
result.push(item);
});
}
return result;
}
function idOf(obj) {
return obj.id;
}
function defaultMerge(newItem, oldItem) {
return angular.merge(oldItem, newItem);
}
function mergeById(oldItems, newItems, idSelector, mergeItem) {
if (mergeItem === undefined) mergeItem = defaultMerge;
if (idSelector === undefined) idSelector = idOf;
// Map retains insertion order
var mapping = new Map();
angular.forEach(oldItems, function(oldItem) {
var key = idSelector(oldItem);
mapping.set(key, oldItem);
});
angular.forEach(newItems, function(newItem) {
var key = idSelector(newItem);
if (mapping.has(key)) {
var oldItem = mapping.get(key);
mapping.set(key, mergeItem(newItem, oldItem));
} else {
// new items are simply added, will be at
// the end of the result list, in order
mapping.set(key, newItem);
}
});
return itemsToArray(mapping);
}
var olds = [
{ id: 1, name: 'old1' },
{ id: 2, name: 'old2' }
];
var news = [
{ id: 3, name: 'new3' },
{ id: 2, name: 'new2' }
];
var merged = mergeById(olds, news);
console.log(merged);
/* Prints
[
{ id: 1, name: 'old1' },
{ id: 2, name: 'new2' },
{ id: 3, name: 'new3' }
];
*/
})();
This builds a Map from the old items by id, merges in the new items, and converts the map back to list. Fortunately the Map object will iterate on the entries in insertion order, according to the specification. You can provide your idSelector and mergeItem functions.
Thanks hege_hegedus. Based on your code, I've written my own and tried to use less loops to speed things up a bit:
function updateCollection(localCollection, fetchedCollection) {
angular.forEach(fetchedCollection, function(item) {
var append = true;
for (var i = 0; i < localCollection.length; i++) {
if (localCollection[i].id == item.id) {
// Replace item
localCollection[i] = item;
append = false;
break;
} else if (localCollection[i].id > item.id) {
// Add new element at the right position, if IDs are descending check for "< item.id" instead
localCollection.splice(i, 0, item);
append = false;
break;
}
}
if (append) {
// Add new element with a higher ID at the end
localCollection.push(item);
// When IDs are descending use .unshift(item) instead
}
});
}
There is still room for improvements, i. e. the iteration through all the objects should use binary search since all items are sorted by id.
The way I'm currently generating my array of dictionaries is very hard-wired in, and I'd rather not do it that way. Top 3 doesn't necessarily have 3 items, I used that name for other reasons. For example, if I know Top 3 will contain two items in addition to the search term, it will look like this:
var top3Titles = [];
var top3Prices = [];
var top3ImgURLS = [];
var top3ItemURLS = [];
//where the title, price, and img url are sent over to the app
matchCenterItems.forEach(function(item) {
var title = item.title[0];
var price = item.sellingStatus[0].convertedCurrentPrice[0].__value__;
var imgURL = item.galleryURL[0];
var itemURL = item.viewItemURL[0];
top3Titles.push(title);
top3Prices.push(price);
top3ImgURLS.push(imgURL);
top3ItemURLS.push(itemURL);
});
// 10 results per MC Item, only showing 4 by default
var top3 =
{
"Top 3":
[
{
"Search Term": searchTerm
},
{
"Title": top3Titles[0],
"Price": top3Prices[0],
"Image URL": top3ImgURLS[0],
"Item URL": top3ItemURLS[0]
},
{
"Title": top3Titles[1],
"Price": top3Prices[1],
"Image URL": top3ImgURLS[1],
"Item URL": top3ItemURLS[1]
},
]
};
return top3;
What I want to do instead is to have the number of dictionaries after the initial Search Term depend on how many item objects there are in the matchCenterItems array. I figured I could do this using a for loop, but I'm not entirely sure how to format it for this purpose. Rather than having separate arrays for titles, prices, etc, I want it to be an object with a title property for example.
You could initialize an array inside top3 and add the objects while iterating over one or your arrays (top3Titles, top3Prices etc).
Like so:
var top3 = {'Top 3': [{'Search Term': searchTerm}]};
for (var i in top3Titles) {
top3['Top 3'].push({
'Title': top3Titles[i],
'Price': top3Prices[i],
'Image URL': top3ImgURLS[i],
'Item URL': top3ItemURLS[i]
});
}
Or, even better, you could replace everything you've posted with:
var top3 = {'Top 3': [{'Search Term': searchTerm}]};
matchCenterItems.forEach(function(item) {
top3['Top 3'].push(
{
'Title': item.title[0],
'Price': item.sellingStatus[0].convertedCurrentPrice[0].__value__,
'Image URL': item.galleryURL[0],
'Item URL': item.viewItemURL[0]
});
});
return top3;
But the point here is, the return belongs inside a function, as I've told you in my comment to your question.
I don't have good practice in JavaScript , but I can give you Demo of How to generate array of dict using for loop
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
var arr=[];
var i;
var text="";
for(i=0;i<10;i++){
<!-- Creating 10 dictionary in array and initialise with some->
<!--value to check->
arr.push({firstName : "John"})
}
<!-- check that dict is working or not->
for(i=0;i<10;i++){
text=text+arr[i].firstName+'<br />'
}
document.getElementById("demo").innerHTML =
text;
</script>
</body>
</html>
you can run and check it ..
I am building a file management system for the web right now.
But I have some problems with javascript array's.
In the system there is an opportunity to add labels to file's.
In javascript I want to have the ID and the value's of the labels with the fileId in 1 array.(as below).
I also want the FileId and the LabelId not as the index of the array's. Because the FileId and labelId can be a realy high number. And then I have an array full of undefined items.
Here an example of how I would like to have it:
array[FileId][labelId,labelValue]
If you have an solution please help me.
Thanks.
You can form structure like this:
arr = [{FieldId:fid_value, Labels:[{labelId:lid_value, labelValue:label_text}]}]
Basically, an array with objects. Each object contains two fields: field id and labels.
Labels is an array with objects also. Each object has label id and label value property.
Code to create new items might be like this:
arr = array();
fieldObj = {FieldId:fid_value, Labels:[]};
fieldObj.Labels.push({labelId:lid_value, labelValue:label_text});
fieldObj.Labels.push({labelId:lid_value, labelValue:label_text});
fieldObj.Labels.push({labelId:lid_value, labelValue:label_text});
...
arr.push(fieldObj);
I'm not entirely sure what you're asking but array within array is possible...
a = []
a.push('a')
Result:
["a"]
a.push(['hello','world'])
Result:
["a",
Array[2]
0: "hello"
1: "world"
]
It sounds like you want objects instead of arrays:
var obj = {};
obj["fieldName"] = {label: "labelname", labelId: 1234};
Then you can access this data as:
obj["fieldName"].label
You could also use an object
var data = {};
data["item1"] = { "labelId" : "foo1", "labelValue" : "bar1" };
data["item2"] = { "labelId" : "foo2", "labelValue" : "bar2" };
console.log(data.item1.labelId);
There are plenty of ways you can strcture the object, it is normally better to use an object than to remember that index 0 is the id and that index 1 is a value.
Use should use objects as well as arrays:
var root = [{
id: '12345',
metadata: {
label: 'foo',
},
type: 'folder',
name: 'Folder Name',
children: [...]
}
];
Now, you can iterate through the folders and files in your root:
for (var i = 0; i < root.length; i++) {
var item = root[i];
console.log(item.type, item.name, item.id);
}
I am using JIT Infovis stacked or mono-valued piechart to do some data visualization. The stacked pie chart takes an object "obj" specifically with the following structure:
This is the hard coded version of jsonObj:
var obj = {
// labelID is unique in each case and may be multiple or just one
'labelID': ['pVal'],
'values': [{ //labelName is unique in each case and will only be one
'labelName': 'name1',
//there may be multiple or just one "values"
//ex, 'values': [80, 40, 15, 10]
'values': 80
}, {
'labelName': 'name2',
'values': [20]
}, {
'labelName': 'name3',
'values': [38]
}, {
'labelName': 'name4',
'values': [58]
}]
};
I'm trying to dynamically populate "obj" with searched data returned to user. But I can not create an empty "obj" with the above specific structure to dynamically populate the data. I tried several times but don't think I'm creating them correctly.
I have three values that I'm trying to dynamically populate into this "obj" but can't get my arms around it. chartID[m], chartArrName[m], chartVal[m].
I need a correct empty "obj" that correspond to the structure defined above.
var "obj" = {
label: ['pVal'],
values: [{
label: [],
values: []
}]
};
for (m = 0; m <= chartArrID.length - 1; m++) {
obj.values[m].label += chartArrName[m];
obj.values[m].values += parseFloat(chartArrVal[m]);
//json.push({label: chartArrName[m], values: parseFloat(chartArrVal[m])});
}
This is not a JSON object. JSON is a lightweight data interchange format. You are just using a object initializer syntax to create an object. You can add what you want of the fly.
var myObj = {};
myObj.name = "foo";
myObj.books = [ "one", "two" ];
myObj.emptyField = null;
myObj.emptyArray = [];
myObj["anotherField"] = "bar"; // this works too
myObj.anotherArray = [];
myObj.anotherArray[0] = {}; // you need to insert something in the first position!
myObj.anotherArray[0].label = "aaa";
myObj.anotherArray[0].value = "bbb";
myObj.anotherArray[0].xyz = "ccc";
myObj.anotherArray[1] = {}; // in the second too, of course!
myObj.anotherArray[1].label = "ddd";
myObj.anotherArray[1].value = "eee";
myObj.anotherArray[1].xyz = "fff";