Check if a key is available in Flex - apache-flex

I have a dictionary with objects as keys. How can I check if specific object is available in the dictionary?

hasOwnProperty won't work if the key is an object rather than a string.
checking that the value is null won't work if the key is in the dictionary, but with a null value.
The 'in' operator seems to work all the time.
var d:Dictionary = new Dictionary();
var a:Object = new Object();
d[a] = 'foo';
var b:Object = new Object();
d[b] = null;
var c:Object = new Object();
trace(a in d);
trace(b in d);
trace(c in d);
Returns
true
true
false
I believe this is a 'more correct' answer than the one posted above.

var b:Dictionary = new Dictionary();
if(b[key] != null) {
}

You can use array syntax and see if the value is null,
assertTrue(myDict["key"] == null)
If nulls are allowed values, use the hasOwnProperty method.
assertTrue(myDict.hasOwnProperty("key")==true)
Adobe, why don't you have a keyExists() function?

The most proper way is to compare the returned value with undefined:
if (dict["key"] !== undefined)
{
// do code when value does exist
}
as a key with a null associated value could exist in a dictionary.
Here is a good article that explains the topic.

You can use in to check for existing keys:
if ('key' in dict)
{
// do something
}
It works with object keys as well:
if (obj in dict)
{
// do something
}
Note that "obj" must be an existing object (defined or not) or it won't compile.

Related

Project to a Known Type using Simple.OData.Client Dynamic Syntax

Simple.OData.Client has a typed and dynamic (and basic) syntax.
I like the typed, but I don't want to build out all my types. In the end I really only need two or so types in the results I get.
But my queries need more types to properly filter the results.
So I want to use the dynamic syntax. But I want to cast the results to classes I have.
I can easily do this manually, but I thought I would see if Simple.OData.Client supports this before I go writing up all that conversion code for each query.
Here is some dynamic syntax code that runs without errors:
client.For(x.Client).Top(10).Select(x.ClientId, x.Name).FindEntriesAsync();
Here is an example of what I had hoped would work (selecting into a new Client object)
client.For(x.Client).Top(10).Select(new Client(x.ClientId, x.Name)).FindEntriesAsync();
But that kind of projection is not supported (I get an "has some invalid arguments" error).
Is there a way to support projection into an existing class when using the dynamic syntax of Simple.OData.Client?
EDIT: The code below works. But it's performance is terrible. I decided to abandon it and write hand written mappers for each type I needed.
This is what I came up with:
dynamic results = oDataClient.For(x.Client).Select(x.ClientId, x.Name).FindEntriesAsync().Result;
var listOfClients = SimpleODataToList<Client>(results);
public List<T> SimpleODataToList<T>(dynamic sourceObjects) where T : new()
{
List<T> targetList = new List<T>();
foreach (var sourceObject in sourceObjects)
{
// This is a dictionary with keys (properties) and values. But no
// matter what sourceObject is passed in, the values will always be
// the values of the first entry in the sourceObjects list.
var sourceProperties = ((System.Collections.Generic.IDictionary<string, object>)sourceObject);
var targetProperties = typeof(Client).GetProperties().Where(prop => prop.CanWrite);
var targetObject = new T();
foreach (var targetProperty in targetProperties)
{
if (sourceProperties.ContainsKey(targetProperty.Name))
{
var sourceValue = GetProperty(sourceObject, targetProperty.Name);
targetProperty.SetValue(targetObject, sourceValue, null);
}
}
targetList.Add(targetObject);
}
return targetList;
}
public static object GetProperty(object o, string member)
{
if (o == null) throw new ArgumentNullException("o");
if (member == null) throw new ArgumentNullException("member");
Type scope = o.GetType();
IDynamicMetaObjectProvider provider = o as IDynamicMetaObjectProvider;
if (provider != null)
{
ParameterExpression param = Expression.Parameter(typeof(object));
DynamicMetaObject mobj = provider.GetMetaObject(param);
GetMemberBinder binder = (GetMemberBinder)Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, member, scope, new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(0, null) });
DynamicMetaObject ret = mobj.BindGetMember(binder);
BlockExpression final = Expression.Block(
Expression.Label(CallSiteBinder.UpdateLabel),
ret.Expression
);
LambdaExpression lambda = Expression.Lambda(final, param);
Delegate del = lambda.Compile();
return del.DynamicInvoke(o);
}
else
{
return o.GetType().GetProperty(member, BindingFlags.Public | BindingFlags.Instance).GetValue(o, null);
}
}
It was made much harder because normal casts and such for the dynamic objects returned would only give the first object in the list over and over. The GetProperty method works around this limitation.

nullable int in linq query [duplicate]

I have a Category entity which has a Nullable ParentId field. When the method below is executing and the categoryId is null, the result seems null however there are categories which has null ParentId value.
What is the problem in here, what am I missing?
public IEnumerable<ICategory> GetSubCategories(long? categoryId)
{
var subCategories = this.Repository.Categories.Where(c => c.ParentId == categoryId)
.ToList().Cast<ICategory>();
return subCategories;
}
By the way, when I change the condition to (c.ParentId == null), result seems normal.
Other way:
Where object.Equals(c.ParentId, categoryId)
or
Where (categoryId == null ? c.ParentId == null : c.ParentId == categoryId)
The first thing to do is to put on logging, to see what TSQL was generated; for example:
ctx.Log = Console.Out;
LINQ-to-SQL seems to treat nulls a little inconsistently (depending on literal vs value):
using(var ctx = new DataClasses2DataContext())
{
ctx.Log = Console.Out;
int? mgr = (int?)null; // redundant int? for comparison...
// 23 rows:
var bosses1 = ctx.Employees.Where(x => x.ReportsTo == (int?)null).ToList();
// 0 rows:
var bosses2 = ctx.Employees.Where(x => x.ReportsTo == mgr).ToList();
}
So all I can suggest is use the top form with nulls!
i.e.
Expression<Func<Category,bool>> predicate;
if(categoryId == null) {
predicate = c=>c.ParentId == null;
} else {
predicate = c=>c.ParentId == categoryId;
}
var subCategories = this.Repository.Categories
.Where(predicate).ToList().Cast<ICategory>();
Update - I got it working "properly" using a custom Expression:
static void Main()
{
ShowEmps(29); // 4 rows
ShowEmps(null); // 23 rows
}
static void ShowEmps(int? manager)
{
using (var ctx = new DataClasses2DataContext())
{
ctx.Log = Console.Out;
var emps = ctx.Employees.Where(x => x.ReportsTo, manager).ToList();
Console.WriteLine(emps.Count);
}
}
static IQueryable<T> Where<T, TValue>(
this IQueryable<T> source,
Expression<Func<T, TValue?>> selector,
TValue? value) where TValue : struct
{
var param = Expression.Parameter(typeof (T), "x");
var member = Expression.Invoke(selector, param);
var body = Expression.Equal(
member, Expression.Constant(value, typeof (TValue?)));
var lambda = Expression.Lambda<Func<T,bool>>(body, param);
return source.Where(lambda);
}
My guess is that it's due to a rather common attribute of DBMS's - Just because two things are both null does not mean they are equal.
To elaborate a bit, try executing these two queries:
SELECT * FROM TABLE WHERE field = NULL
SELECT * FROM TABLE WHERE field IS NULL
The reason for the "IS NULL" construct is that in the DBMS world, NULL != NULL since the meaning of NULL is that the value is undefined. Since NULL means undefined, you can't say that two null values are equal, since by definition you don't know what they are.
When you explicitly check for "field == NULL", LINQ probably converts that to "field IS NULL". But when you use a variable, I'm guessing that LINQ doesn't automatically do that conversion.
Here's an MSDN forum post with more info about this issue.
Looks like a good "cheat" is to change your lambda to look like this:
c => c.ParentId.Equals(categoryId)
You need to use operator Equals:
var subCategories = this.Repository.Categories.Where(c => c.ParentId.Equals(categoryId))
.ToList().Cast<ICategory>();
Equals fot nullable types returns true if:
The HasValue property is false, and the other parameter is null. That is, two null values are equal by definition.
The HasValue property is true, and the value returned by the Value property is equal to the other parameter.
and returns false if:
The HasValue property for the current Nullable structure is true, and the other parameter is null.
The HasValue property for the current Nullable structure is false, and the other parameter is not null.
The HasValue property for the current Nullable structure is true, and the value returned by the Value property is not equal to the other parameter.
More info here Nullable<.T>.Equals Method
Or you can simply use this. It will also translate to a nicer sql query
Where((!categoryId.hasValue && !c.ParentId.HasValue) || c.ParentId == categoryId)
What about something simpler like this?
public IEnumerable<ICategory> GetSubCategories(long? categoryId)
{
var subCategories = this.Repository.Categories.Where(c => (!categoryId.HasValue && c.ParentId == null) || c.ParentId == categoryId)
.ToList().Cast<ICategory>();
return subCategories;
}
Linq to Entities supports Null Coelescing (??) so just convert the null on the fly to a default value.
Where(c => c.ParentId == categoryId ?? 0)

ActionScript-3 : Array vs. ArrayList

Can anybody say me what is faster: Array or ArrayList? (ActionScript3)
I tried to find a page about this but didn't find anything.
Thank you.
The ArrayList class is a simple implementation of IList that uses a backing Array as the source of the data. Items in the backing Array can be accessed and manipulated using the methods and properties of the IList interface. Operations on an ArrayList instance modify the data source; for example, if you use the removeItemAt() method on an ArrayList, you remove the item from the underlying Array.
Apparently ArrayList class wraps an Array object - hence a plain Array would be faster than an ArrayList object.
As already stated, Array is faster. Actually it is orders of magnitude faster.
The equivalents of array access are getItemAt and setItemAt.
Implementation:
public function getItemAt(index:int, prefetch:int = 0):Object
{
if (index < 0 || index >= length)
{
var message:String = resourceManager.getString(
"collections", "outOfBounds", [ index ]);
throw new RangeError(message);
}
return source[index];
}
and:
public function setItemAt(item:Object, index:int):Object
{
if (index < 0 || index >= length)
{
var message:String = resourceManager.getString(
"collections", "outOfBounds", [ index ]);
throw new RangeError(message);
}
var oldItem:Object = source[index];
source[index] = item;
stopTrackUpdates(oldItem);
startTrackUpdates(item);
//dispatch the appropriate events
if (_dispatchEvents == 0)
{
var hasCollectionListener:Boolean =
hasEventListener(CollectionEvent.COLLECTION_CHANGE);
var hasPropertyListener:Boolean =
hasEventListener(PropertyChangeEvent.PROPERTY_CHANGE);
var updateInfo:PropertyChangeEvent;
if (hasCollectionListener || hasPropertyListener)
{
updateInfo = new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE);
updateInfo.kind = PropertyChangeEventKind.UPDATE;
updateInfo.oldValue = oldItem;
updateInfo.newValue = item;
updateInfo.property = index;
}
if (hasCollectionListener)
{
var event:CollectionEvent =
new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
event.kind = CollectionEventKind.REPLACE;
event.location = index;
event.items.push(updateInfo);
dispatchEvent(event);
}
if (hasPropertyListener)
{
dispatchEvent(updateInfo);
}
}
return oldItem;
}
There's a LOT of calls and checks involved here. Please note, that _dispatchEvents == 0 is true by default (unless you disableEvents), thus writing in fact is an immense operation.
However ArrayList does provide a lot of feature, that are usefull within flex. A good compormise is to grab the underlying Array (accessible as ArrayList::source), peform your operations, and then reassign it (supposing you have listeners observing that Array).
Also, if you go with Flash Player 10, then Vector will outperform Array.
greetz
back2dos
Array is probably slightly faster or they are equal. All an ArrayList is, is an implementation of iList that uses an... Array as a backing object.

Flex looping through object

Im trying to extend the flex ArrayCollection to be able to search for an object containing specific data and give it back.
Here is my function:
public function getItemContaining(value: String): Object {
//Loop through the collection
for each(var i: Object in this) {
//Loop through fields
for(var j: String in i) {
//If field value is equal to input value
if(i[j] == value) {
return i;
}
}
}
//If not found
return null;
}
Problem is j is always null so the second loop never works. So I read flex loop descriptions and actually it should work just fine. What can possibly be the problem?
Try it like this:
for (var name:String in myObject){
trace(name + ":" + myObject[name];
}
Okay that was actually the same you were doing. The error must be in this line:
for each(var i: Object in this) {
Try using this:
for each(var i: Object in this.source) {
My first instinct would be to have a look at data type. You're setting up a loop declaring j:String and the symptom is that j is always null. This suggests to me that Flex is failing to interpret the elements of i as strings. If Flex only recognizes the elements of i as Objects (because all Strings are Objects, and Objects are the lowest common denominator), it would return null for j:String.
Try this for your inner loop:
for(var j: Object in i) {
//If field value is equal to input value
if(i[j] is String && (i[j] as String) == value) {
return i;
}
}
if you are using ArrayCollection as your datasource, you should look at using the IViewCursor interface. You can supply a custom compare function, or supply the fields top compare to. This interface is well documented with examples in adobe/livedocs
var _cursor:IViewCursor;
var _idSortField:SortField;
var _idSort:Sort = new Sort();
_idSortField = new SortField();
_idSortField.compareFunction = this.myCompareFunction;
_idSort.fields = [_idSortField];
myArrayCollection.sort = _idSort;
myArrayCollection.refresh();
_cursor = myArrayCollection.createCursor();
if (_cursor.findAny(search))
return _cursor;
if you are search for a value in a specific property, then its even easier. Here's the link to adobe livedocs on this topic

Does An Object Have "Children"

I just want to know if the object in question, has any sub-objects within it or not.
Do I really have to do THIS:
public static function getLength(o:Object):bool
{
for (var item:* in o)
if (item != "mx_internal_uid")
return true;
return false;
}
Isn't there some way to say SOMETHING LIKE: Object.hasChildren();
OR EVEN Object.childCount();
The Object in question does NOT extend the DisplayObjectContainer. It is just something like:
var Ob:Object;
Ob.SomeProp="xxx";
Ob.SomeOtherProp="zzz";
How can I know how many "entries" there are in the object. (in this case 2).
In other words, how does "for (var item:* in Ob)" know when to stop.
???
A good class to inspect objects is the flex built in ObjectUtil. I think what you're trying to achieve would be done by using (obj is the object to analyze):
ObjectUtil.getClassInfo(obj).properties.length
But ObjectUtil.getClassInfo would be a good place too look if you're trying to analyze an object, it returns a lot of information (read more on LiveDocs).
It also has a function to check if a variable is a simple one - ObjectUtil.isSimple
By object you mean the Object class, hence counting the properties, or the object on the displaylist, if the latter, that objects surely extends DisplayObjectContainer wich has the numChildren property
As kajyr says, if it's a DisplayObjectContainer you can check for numChildren.
If you want to check if a generic objects contains simple properties ( primitives like Number,int, uint, String, Boolean ) or complex properties (subObjects, instances of some class ) that you might regards as children to that generic object, you do the following:
var testObj:Object = {id:1,name:'DumDum'};
var testObj2:Object = {id:2,name:'NumNum',data:[1,2,3,4,5,6,7,8,9],somethingComplex:{firstName:'Num',lastName:'Num'}};
trace(isSimple(testObj).length == 0);//prints true
trace(isSimple(testObj2).length == 0);//prints false
trace(isSimple(testObj2));
function isSimple(obj:*):Array{
var complex:Array = [];
for(var prop in obj){
if(!(obj[prop] is String || obj[prop] is int || obj[prop] is uint || obj[prop] is Number || obj[prop] is Boolean))
complex.push({prop: obj[prop]});
}
return complex;
}
If you want to get the number of members (variables associated with an object), that is easy enough to get:
var Ob:Object = {};
Ob.SomeProp="xxx";
Ob.SomeOtherProp="zzz";
trace(getMembersNum(Ob));//prints 2
function getMembersNum(obj:*):int{
var result:int = 0;
for(var prop in obj) result++;
return result;
}
You would write this in your utility package/class maybe like this:
public static function get numMembers(obj:*):int{
var result:int = 0;
for(var prop in obj) result++;
return result;
}
HTH

Resources