I need to find the number of Events stored in EventList from the events extracted from the calendar.
There was no size() method found.
Below is the code
EventList eventList = (EventList)PIM.getInstance().openPIMList(
PIM.EVENT_LIST, PIM.READ_WRITE);
Enumeration eventsList = eventList.items(EventList.STARTING, startDateEvent, endDateEvent, false);
How can I find the number of events in the eventsList Enumeration?
Unfortunately, if you just want the number of events between your start and end dates, you'll need to count them. Enumeration doesn't provide any interface for getting the number of elements.
EventList eventList = (EventList)PIM.getInstance().openPIMList(
PIM.EVENT_LIST, PIM.READ_WRITE);
Enumeration eventsList = eventList.items(EventList.STARTING, startDateEvent, endDateEvent, false);
int numEvents = 0;
while (eventsList.hasMoreElements()) {
eventsList.nextElement();
numEvents++;
}
System.out.println("There are " + numEvents + " events in the list");
If you still want to iterate over the list after this counting, you'll need to get a new Enumeration object by calling eventList.items() again.
If, however, you want the number of events in the entire eventList, then you can get the size by casting your full list to a BlackBerryEventList:
From the BlackBerry API docs:
Any instance of EventList that is retrieved from PIM.openPIMList()
when specified pimListType==PIM.EVENT_LIST will be an instance of
BlackBerryEventList and can be successfully casted to
BlackBerryEventList, if desired, in order to use the RIM extension
functionality.
So, what you should do is cast your list to a BlackBerryEventList (or a BlackBerryPIMList), and then you can do this:
EventList eventList = (EventList)PIM.getInstance().openPIMList(
PIM.EVENT_LIST, PIM.READ_WRITE);
if (eventList instanceof BlackBerryEventList) { // should always succeed
BlackBerryEventList bbEventList = (BlackBerryEventList)eventList;
int sizeOfList = bbEventList.size();
}
Related
I'm trying to copy one field to another field in the same table with 10,000 + records, in batches of 50 using the Scripting App.
What am I doing wrong in this code block? It only copies the first record. If I remove the await, it'll copy 15 records then stop.
let table = base.getTable('Merchants');
let view = table.getView('Grid view');
let query = await view.selectRecordsAsync();
let records = query.records;
updateLotsOfRecords(records);
async function updateLotsOfRecords(records) {
let i = 0;
while (i < records.length) {
const recordBatch = records.slice(i, i + 50);
for (let record of recordBatch) {
let sourceValue = record.getCellValue('Merchant');
await table.updateRecordAsync(record, { 'LogoBase64': sourceValue });
}
i += 50;
}
}
you should use updateRecordsAsync function, not updateRecordAsync
When using single update function in loop, there is no sense to divide it into batches.
You exceed some limit of calls per second, that's why it stops.
For multiple updates, you need to use updateRecordsAsync, like this
while (recordsToWrite.length > 0) {
await updates.updateRecordsAsync(recordsToWrite.slice(0, 50));
recordsToWrite = recordsToWrite.slice(50);
}
Data that you should pass to it, more complex. I learned JS for 3 months and still have difficulties understandins all these "arrays of arrays of objects, passed via object's property". But that's the key to unerstand JS.
It's quite hard to leave basic/pascal habits, with plenty of inserted FOR loops, and GOTO sometimes))
I think, you already found the answer for 2 months, so my answer may be useless, but when i write it here, maybe i understand it better for myself. And help to some beginners also.
For single write, you pass (record, Object), where object is {field:'Value}
For multiple, you should pass
Array of Objects, where
Object is {id:recordID, fields:{object2}} , where
object2 is array of obj3 [ {obj3},{obj3}, {obj3} ], where
obj3 is a { 'Name or ID of field': fieldvalue }
you script might be:
let query = await view.selectRecordsAsync();
let updates=query.records.map(rec=>{
Map method can be applied for arrays, and 'query.records' is array of records. Here
'rec' is loop variable inside this "arrowfunction"
now let's create obj3 , in our case { 'Name or ID of field': fieldvalue }
{'LogoBase64':rec.getCellValue('Merchant')}
wrap it into fields property
fields:{'LogoBase64':rec.getCellValue('Merchant')}
and add record id
wrapping as Object.
To avoid complex string with linebreaks, and to make object creation easier, we can do it with function:
{rec.id, fields:{'LogoBase64':rec.getCellValue('Merchant')}}
fuction myObj(rec){return {rec.id, fields:{'LogoBase64':rec.getCellValue('Merchant')}}
map(rec=>myObj(rec)) - can be written as map(myObj)
we need array of objects, and map method gets first array, doing something with each element and return other array, of results. like we need.
and now finally we get
let table = base.getTable('Merchants');
let view = table.getView('Grid view');
let query = await view.selectRecordsAsync();
function myObj(rec){return {'id':rec.id,'fields':{'Logobase64':rec.getCellValue('Merchant')}}};
let updates=query.records.map(myObj);
while (updates.length > 0) {
await table.updateRecordsAsync(updates.slice(0, 50));
updates = updates.slice(50); }
From healthkit, I will receive some datas, for example steps data.
I save in my server this datas. Il have then an array of datas:
1.- startDate, endDate, value
2.- startDate, endDate, value
etc
It can be very lot of values in my server.
Then I get the values in the Healthkit. I have lot of values. Values who are in the server and new values.
I want to upload to the server only the new values.
I do so:
for each value in my server {
for each value in healthkit{
if(startDate, endDate and value are not equal to the value in the server){
then save the value in the server
}
}
}
The algo will work, but it's very very slow. I can have lot of values in the two systems. Most of them the same in the two places.
Have you an idea how to do better?
I cannot save a flag in the healthKit.
I'm using ionic with angular 4 and typescript.
This answer assumes that the data on your server and the data from healthKit are sorted in the same way, or that you can sort them without affecting anything else.
For example you can sort your data on the server and the data from healthKit by StartDate, break ties by EndDate, then break ties by value.
Now you have two sorted arrays that you want to merge. The idea is to use the merge function of merge sort explained here.
You will end up with an array containing all the data without repetitions, which you can save on your server.
Edit:
void mergeArrays(int arr1[], int arr2[], int n1,
int n2, int arr3[])
{
int i = 0, j = 0, k = 0;
// Traverse both array
while (i<n1 && j <n2)
{
// Check if current element of first
// array is smaller than current element
// of second array. If yes, store first
// array element and increment first array
// index. Otherwise do same with second array
if (arr1[i] < arr2[j])
arr3[k++] = arr1[i++];
else if (arr2[j] < arr1[i])
j++;
else
j++,i++;
}
// Store remaining elements of first array (healthKit Array)
while (i < n1)
arr3[k++] = arr1[i++];
}
I think I need a bit more context to understand the problem. By "new" values, are you including entries that have been modified, or just new entries that have been added?
If you only need the new values, and they are being added to the end of the array on the client side, then you can just take them from the end of the array.
const new_count = healthkit.length - myserver.length, // number of new entries
index_start = healthkit.length - new_count, // index in healthkit array where new entries start
new_values = healthkit.slice(index_start); // new array containing only new entries
addNewValues(new_values);
Now you have the new values in a separate array, and you can update them to the server.
If it is the case that you do need to update values that have changed, you can iterate over both arrays (only once, and at the same time) and find the differences. I am going to assume that the entries are in the same index for both arrays. I'm also assuming the "value" key is the only one you want to compare. You can do the following to find the values that have been modified.
const modified_values = [];
myserver.forEach(function(entry, i) { // iterate over server array
let healthkit_entry = healthkit[i]; // get healthkit entry with same index
if(entry.value !== healthkit_entry.value) { // see if value has changed
modified_values.push(healthkit_entry); // if changed, add to modified array
}
});
updateModifiedValues(modified_values);
Now the modified_values array has all of the modified entries from the healthkit array.
I am receiving an array in route data containing different string values. Since I don't know how many string values I am going to receive, I cant have a definite Where function. Hence I am looping through the array and making multiple calls to DB set, fetching the result and adding it into another Master List. Please see code below.
public JsonResult GetModels(string brand)
{
string[] brands = brand.Split(seperator);
MasterList.Clear();
for (int i = 0; i < brands.Length; i++)
{
tempString = brands[i];
tempList = db.Devices.Where(r => r.Brand.Equals(tempString)).Select(r => new MySelectList { Value = r.PhoneModel, Text = r.PhoneModel }).Distinct().ToList();
for (int a = 0; a < tempList.Count; a++)
MasterList.Add(tempList[a]);
}
return Json(MasterList, JsonRequestBehavior.AllowGet);
}
Is there a way I can somehow avoid looping through the array and use it directly in Where function? Meaning Where function can look into values of the array and return result based on it.
You can do this by using Contains. This effectively generates an SQL IN clause:
tempList = db.Devices.Where(r => brands.Contains(r.Brand));
Given a Map, assignment, what is the fastest way to check if it contains any duplicate values in Dart? I am currently using a Set formed from the Map's values and checking its length against the original Map, which works of course, but I'm wondering if there's an especially performant alternative.
Set d = new Set.from(assignment.values);
if (d.length < assignment.length) {
return false; // indicates has duplicates in this context
}
EDIT:
Tried #mezoni's solution modified for my program, but it actually ran a bit slower than my original version. It probably has more to do with constant times than anything else.
List values = new List.from(assignment.values);
Set set = new Set();
for (var i = 0; i < assignment.length; i++) {
if (!set.add(values[i])) {
return false;
}
}
Complexity wise you won't be able to get anything faster. Creating the Set and filling it with the values of the Map is linear in the number of elements. Clearly you have to run through all the values, so you can't do any better than that.
Maybe you could find a solution with a smaller constant factor, but that's not clear. In particular for larger sets I think the Set solution is pretty efficient.
This is more of a algorithms question than a Dart question. In any case, you have to check every value against the others, giving n-1 + n-2 + ... + n-(n-1) checks, or n^2/2. Programmatically, it's easy to create a set, but you could also generate an array, sort the array, and then iterate once to check for duplicates. That finishes in O(n log n).
Fastets way (if you realy need better performance):
void main() {
// Values from map
var values = [1,2,3,2,1,3,2,1];
var length = values.length;
var set = new Set();
var duplicate = false;
// Only for statistics purpose
var statistics = 0;
for(var i = 0; i < length; i++) {
statistics++;
if(!set.add(values[i])) {
duplicate = true;
break;
}
}
print("Duplicate: $duplicate");
print("Performed in ${statistics} iteration(s) from $length possible");
}
Output:
Duplicate: true
Performed in 4 iteration(s) from 8 possible
P.S.
The first example can be recommended to use with List values.
But because Map.values not a List but Iterable then it would be more efficient do not convert them to List but use as is.
Here is modified sample for use with Iterable objects.
It will be work faster because in this algorithm not required convert all values to the List object because it not want using of all elements without exception.
Instead it wants use as less as possible access operation on original source. If the source supports lazy operation of the access to values (as Iterable) this will be even better.
void main() {
// Values from map
var values = [1,2,3,2,1,3,2,1];
var assignment = {};
var length = values.length;
var key = 0;
for(var value in values) {
assignment[key++] = value;
}
var set = new Set();
var duplicate = false;
// Only for statistics purpose
var statistics = 0;
for(var value in assignment.values) {
statistics++;
if(!set.add(value)) {
duplicate = true;
break;
}
}
print("Duplicate: $duplicate");
print("Performed in ${statistics} iteration(s) from $length possible");
}
Is there a generic way to retrieve PropertyInfo based on a string value alone, when deeper than one level.
I assume this is probably simple enough, but my search results are only as good as my search criteria, and I think I am having an issue articulating the proper keywords to get search results for what I am after.
I would like to be able to do something like the following (which works perfect if the key is for a direct property / one level - ie key = 'firstName'):
public static PropertyInfo (this HtmlHelper htmlHelper, string key) {
PropertyInfo pInfo = htmlHelper.ViewData.Model.GetType().GetProperty(key);
return pInfo;
}
But is there a way for me to return the PropertyInfo based on a string alone
when Key equals something more complex, such as nested classes, objects, lists, etc...:
key = "somelist[0].myproperty"
key = "Items[0].someotherlist[1].someproperty" (where Items is defined as List<Item> Items {get; set;}, someotherlist is defined similarly)
Can the method be generic enough to essentially drill down as many levels as needed (defined)?
So here is what I came up with... this is about to get wordy, and mostly 'stream of thought'
I have custom HtmlHelperExtension, and within it :
PropertyInfo[] pInfoArray = htmlHelper.ViewData.Model.GetType().GetProperties();
PropertyInfo pInfo = GetPropertyInfo(pInfoArray, key);
This GetPropertyInfo() method takes the key, and the PropertyInfo array, cycles through the properties, until the keypart (using regex to remove any indication of an array from the string, so I am left with only the property) matches the property name. On Match, determine if this is the first cycle in the loop, and if so assign the matched property to my Temp Type and PropertyInfo variables. If keyParts are remaining to loop through, subsequent loops now use previously set temp variables and the for loop index [i] to iterate / drill down the class structure. Each time setting the pInfoTemp variable, and then pTypeTemp so the next loop can use where it left off.
private static PropertyInfo GetPropertyInfo(PropertyInfo[] pInfoArray, string key)
{
PropertyInfo pInfo = null;
string[] keyParts = key.Split('.');
Regex arrayRgx = new Regex("\\[\\d*\\]");
PropertyInfo pInfoTemp = null;
Type pTypeTemp = null;
foreach (PropertyInfo prop in pInfoArray)
{
string keyPartsTrimmed = arrayRgx.Replace(keyParts[0], ""); // removes '[#]' from string
if (keyPartsTrimmed == prop.Name) // match property name
{
for (int i = 0; i < keyParts.Count(); i++)
{
if (i == 0) // initial item [0]
{
pTypeTemp = prop.PropertyType; // gets [0]'s type
pInfoTemp = prop; // assigns [0]'s property info
}
else
{
pInfoTemp = GetNestedPropertyInfo(pTypeTemp, arrayRgx.Replace(keyParts[i], "")); // gets [i]'s property info for return or next iteration
pTypeTemp = pInfoTemp.PropertyType; // gets [i]'s type for next iteration
}
}
pInfo = pInfoTemp;
break;
}
}
return pInfo;
}
This next method is invoked by the previous for grabbing nested property info, more importantly for detecting whether the passedItemType is a List (without this, it fails to work correctly as it is unable to find the property asked for in a List<> Type. I need to know what the List item Type is.
private static PropertyInfo GetNestedPropertyInfo(Type passedItemType, string passedProperty)
{
PropertyInfo pInfoOut = null;
if (passedItemType.IsGenericType && passedItemType.GetGenericTypeDefinition() == typeof(List<>))
{
Type itemType = passedItemType.GetGenericArguments()[0];
pInfoOut = itemType.GetProperty(passedProperty);
}
else
{
pInfoOut = passedItemType.GetProperty(passedProperty);
}
return pInfoOut;
}
This currently suits my requirements as they are today, and I have tested it with the following properties, lists, subclasses, subclasses with lists, etc.. to 4 levels deep, but should function properly no matter the depth:
firstName
lastName
Items[1].sprocket
subClass.subClassInt
subClass.mySubClassObj.sprocketObj
subClass.ItemsInMySubClass[1].sprocket
subClass.ItemsInMySubClass[0].mySubClassObj.widgetObj
subClass.ItemsInMySubClass[2].mySubClassObj.sprocketObj
If anyone has a better solution, or see any potential issues with what I have, I welcome the feedback.
The best way in your case is to make a parser that split that expression.