Flex Dictionary Sorting - apache-flex

I have the following dictionary in flex, and i d like to sort it by value. Couldn't find any resource.
'1'=>2, '0' =>1, '3'=>4 ..
Any ideas ? How can i sort this by value ?

I searched around for a similar solution, except that I needed to sort the dictionary map and return a sorted collection relating key value pairs. After failing to find a published solution I put together the approach below. This method takes a dictionary as input, creates an array maintaining the association then sorts the resultant array using array.sortOn() and returns the sorted results back as an array. "key" and "value" fields in the array in the example below are used for clarity, but any field name could be used.
This example assumes a string object as a key and a numeric object as a value, though of course any object type could be used, and field parameters adjusted.
The approach below could also be used for sorting by key instead of value by using "key" as the sort field for the sortOn method, and you could use different sort options than the descending numeric sort I used here( AS3 SortOn() documentation) Code below is intentionally non-generic to simplify it for example purposes.
public static function sortDictionaryByValue(d:Dictionary):Array
{
var a:Array = new Array();
for (var dictionaryKey:Object in d)
{
a.push({key:dictionaryKey,value:d[dictionaryKey]});
}
a.sortOn("value",[Array.NUMERIC|Array.DESCENDING]);
return a;
}

Probably not the best way to do it but it works:
var a:Array = new Array();
for each (var v:Number in dict)
{
a.push(v);
}
a.sort();

Related

foreach statement cannot operate on variables of type 'Diary_Entry'

Passing in a list of dates 'DiaryEntry' through the foreach loop. every date that it records will be highlighted on the calendar....
foreach (DateTime d in DiaryEntry)
{
Calendar1.SelectedDates.Add(d);//CALENDAR1 being the ID of the calendar on the aspx page
}
ERROR: foreach statement cannot operate on variables of type 'Diary_Entry' because 'Diary_Entry' does not contain a public defination for 'GetEnumerator'
Anyone have any idea how I can resolve this?
Thanks
Is Diary_Entry meant to be a list of some kind? Is it based on a collection class, something that implements System.Collections.IEnumerable or System.Collections.Generic.IEnumerable? If not, if it just has a couple of properties that represent dates, you can't use foreach with it. You'd have to process each property separately.
Calendar1.SelectedDates.Add(Diary_Entry.Date1);
Calendar1.SelectedDates.Add(Diary_Entry.Date2);
// etc.
If it has two dates, representing a start and end date, and you want to iterate through the range, you wouldn't be able to use foreach with it, but you could still use for:
for(DateTime d = Diary_Entry.StartDate;d<=Diary_Entry.EndDate;d=d.AddDays(1))
{
Calendar1.SelectedDates.Add(d);
}
Your DiaryEntry object needs to implement IEnumerable or IEnumerable<T>.
From msdn:
The foreach statement repeats a group of embedded statements for each
element in an array or an object collection that implements the
System.Collections.IEnumerable or
System.Collections.Generic.IEnumerable<T> interface.
I suspect you mean to have an array or some other collection of those objects. In that case you could iterate over the collection with a foreach. Another possibility is that DiaryEntry has a collection property on it, and you mean to iterate over that... like the following maybe?
foreach(DateTime date in DiaryEntry.Dates)
{
...
}

In a C# TBB: how to split a multi SingleLineTextField into seperate strings

I have a plain textfield in Tridion that can have multiple values. The itemtype is a SingleLineTextField.
In the TBB code I have the following (removed the non-essential parts):
ItemFields itemFields = new ItemFields(folder.Metadata, folder.MetadataSchema);
foreach (ItemField itemField in itemFields)
{
string itemFieldValue = string.Empty;
switch (Utilities.GetFieldType(itemField))
{
case FieldType.SingleLineTextField:
itemFieldValue = itemField.ToString();
break;
}
}
Now the result in case of two entries is just two strings with a character line break in it.
String A
String B
The method used is a generic one, which also works on other fields, so I was looking for some way to find out if a SingleLineTextField has more values in it.
You can cast the field to a SingleLineTextField type, then iterate through the Values collection, something along these lines:
SingleLineTextField field = (SingleLineTextField)itemField;
foreach(string value in field.Values)
{
// do something with value
}
// or if all you want is the count of values
int i = field.Values.Count;
Firstly, I would advise against relying on the ToString() method on objects unless it is specifically documented. In this case it works with the abstract class ItemField, but this may not always be the case.
The TOM.Net API only defines Definition and Name properties for ItemField, so you need to cast your ItemField object to something more specific.
the TextField abstract class, which SingleLineTextField inherits from, defines a ToString() method, but also Value and Values properties, which are much better suited to what you're trying to do. Looking at the documentation, we can see that Values will give us an IList<String> of the values, even if your field is not multi-valued. Perfect!
So, to answer your question, "I was looking for some way to find out if a SingleLineTextField has more values in it", you need to cast your ItemField as a TextField and check the number of Values it provides, thus:
TextField textField = (TextField)itemField;
// If you need to deal with multi-valued fields separately
if (textField.Values.Count > 1)
{
//Logic to deal with multiple values goes here
}
else
{
//Logic to deal with single valued goes here
}
// Much better... If you can deal with any number of values in a generic fashion
foreach (string value in textField.Values)
{
// Generic code goes here
}

Dictionary Keys (List<int>) Retrieve in C#

Assumed I defined my dict as below.
Dictionary<list<int>, list<string>> d = new Dictionary<List<int>, list<string>>()
How can I retrieve the dict key and value rapidly.
[update]
I want to get the Key - List content.
I tried a simple way as below
List<int> KeysList= new List<int>(d.Keys);
But it doesn't work at the complex key on my case.
Can I only use the KeyValuePair as below?
foreach (KeyValuePair<List<int>, List<string>> pair in d)
{
KeysList= new List<int>(pair.Key);
}
You've got a potential problem there to start with: List<T> doesn't override Equals, so you'd have to use the exact same key reference to fetch the value for a key.
Having said that, if you have that reference, it's as simple as
List<string> value = d[key];
or
List<string> value;
if (d.TryGetValue(key, out value))
{
...
}
It's pretty unusual to have a List<T> as a key though - can you tell us more about what you're trying to do? There may be a better approach.

flex 3 and using name/value pairs

Does anyone have any recommendations for working with name/value pairs in Flex?
Context:
I want to create a Flex UI for updating a database table. I want the UI to contain the field name(read only) and current field value (which will be editable). Im using the WebService component to retrieve the field value and then asssigning it to an object with the field name hardcoded e.g.
private function resultHandler(event:ResultEvent):Object
{
var resultsObj:Object;
resultsObj = {
name:event.result.name as String,
This approach however is adding the dependency that the table structure/field names will never change. Using the object type also requries that i write my own algorithm to sort the output.
I'm not sure I understand the issue.
If you want to avoid dependency of the properties returned from the event at this point, simply use the event.result object, which is already an associative array.
As for sorting, we would need more context on what you are attempting to sort.
That's pretty simple. Don't use for each in loop. Use For-In Loop
Demo is shown below.
var dicEntry:Object = new Object();
dicEntry["Name"] = "Raj";
dicEntry["sal"] = 10000;
dicEntry["age"] = 33;
for(var key:Object in dicEntry)
{
trace("Object Key: "+key+" Object Value: +dicEntry[key]);
}
That's it.

How do I find the length of an associative array in ActionScript 3.0?

Is there a simple way to retrieve the length of an associative array (implemented as an Object) in ActionScript 3.0?
I understand that there are two primary ways of creating associative arrays in AS3:
Use a Dictionary object; especially handy when the key does not need to be a string
Use an Object, and simply create properties for each desired element. The property name is the key, and the value is, well, the value.
My application uses approach #2 (using the Object class to represent associative arrays).
I am hoping there is something more native than my for loop, which manually counts up all the elements.
You have to count them in a for loop as you do. Of course, you could make a class and stick the for loop in that class.
For some great implmentations of Collections in AS3, check these guys.
Edit 2013 Not surprisingly, links do break after time. Try this new one: http://www.grindheadgames.com/get-the-length-of-an-object.
Doing a few tests on this has actually surprised me. Here's normal use of an Array:
var things:Array = [];
things.push("hi!");
trace(things.length);
// traces 1
trace(things);
// traces hi!
Here's if we set a value to a string:
var things:Array = [];
things["thing"] = "hi!";
trace(things.length);
// traces 0
trace(things);
// traces an empty string
trace(things["thing"]);
// traces hi!
Basically if you add things using strings you're setting properties rather than actually adding to the array. Makes me wonder why Array is dynamic in this way.
So... yeah count the items with a for ... in loop!
I think you're stuck with counting them "manually".
An option would be to wrap the whole thing in a class and keep a separate variable that you update as you add/remove.
var count:int;
var key:String;
for (key in myObject)
{
count++;
}
trace ("myObject has this many keys in it: " + count);
or, alternatively, the for-each syntax (I haven't tested to see which is faster)
for each (var o:* in myObject)
{
count++;
}

Resources