Changes to one variable propagates to another - apache-flex

For example I have two ArrayCollection's - firstAC and secondAC. If I do secondAC = firstAC, and than I make changes to secondAC (prehaps put a filterfunction on it) it somehow propagates to firstAC, would anyone tell me why that happens in Flex or Actionscript 3?
What can I do if I only want secondAC to get all data from firstAC but then when I make changes to secondAC it does not show in firstAC?
Thanxs a bunch for answers!
Ladislav

When you write secondAC = firstAC, you simply state that secondAC and firstAC are references to the same array collection.
What you want is to clone the first collection (as in, copy all elements one by one).
You should be able to do it with something like :
secondAC = new ArrayCollection();
secondAC.addAll(firstAC);

I have no idea of Flex or Actionscript, but looks like firstAC and secondAC point to the same array, therefore that's expected.
What you should do is just create another array, copy members, and they will be two real different entities.

Instead of secondAC = firstAC, you can try secondAC.addAll(firstAC).

In ECMAScript languages (AS1-3, JavaScript, et al.), when you use
var foo = //some value which is not a String or a Number
what you are really saying is "foo now points to the same object as that other variable." This means that in this situation, both arrays will be the same value:
var foo:Array = [ 1, 2, 3 ];
foo = bar;
bar.push( 4 );
trace( foo ); // 1, 2, 3, 4
This also works for functions:
var foo:Array = [ 1, 2, 3 ];
adder( foo );
function adder( bar:Array ):void {
bar.push( 4 );
}
trace( foo ); // 1, 2, 3, 4
and it even works with XML:
var xml:XML = <root><foo/></root>;
var bar:XML = xml;
bar.children()[ 0 ].#bar = 1;
trace( xml.toXMLString() ); // <root><foo bar="1"/></root>
This is called "passing by reference" instead of "passing by value" or "passing by copy". It means that every time that an item is referenced, each variable will point to the same object.
There are many ways to get around this, and most of them depend on your context. For arrays, my favorite is Array.concat(), which returns a literal clone of the array. This means that anything I do to the returned value will not effect the original in any way. If I'm dealing with XML, however, I will do something like: var xml2:XML = XML( xml.toXMLString() );.
In your case, I would actually recommend that you use:
var secondAC:ArrayCollection = new ArrayCollection( firstAC.source.concat() );
This has the major benefits of not only being faster (it relies on compiled code instead of Flex SDK code and it also does not first instantiate a new array and then re-populate it), but it also has the distinct benefit of being available in older versions of Flex 3's SDK -- it is entirely backwards compatible.

Related

GMS2 returns instance_create_layer :: specified layer "text_layer" does not exist even though the layer exists how do i fix this?

heres the code
var _obj;
if (instance_exists(obj_text)) _obj = obj_txt_queued; else _obj = obj_text;
with (instance_create_layer(0, 0, "text_layer", _obj))
{
msg = argument[0];
if (instance_exists(other)) originInstance = other.id else originInstance = noone;
if (argument_count > 1) background = argument[1]; else background = 1;
}
with (obj_phae)
{ if (state != scr_player_state_lock)
{
lastState = state;
state = scr_player_state_lock;
}
}
[layers](https://i.stack.imgur.com/9u9tD.png)
I tried removing any extra rooms that were not needed and I tried changing the layer name to something else.
I also tried using var instance_create_layer() but that obviously didn't work
I'm a bit confused at this part:
with (instance_create_layer(0, 0, "text_layer", _obj))
Especially the with(), as that function will go through every object in the room if it sees an object within the parameter, since you suggested to create a new object with it, I'm surprised it doesn't create an infinite loop. Maybe it works, I've never tried it myself, but I think there's a more logical way to assign variables from one object to a newly created object.
Assuming you want to use the With() statement to address the variables within the _obj, I think you can manage something similair through this function:
var object = instance_create_layer(0, 0, "text_layer", _obj)
object.msg = argument[0];
object.originInstance = id
if (argument_count > 1) object.background = argument[1]; else object.background = 1;
It's probably a given at this point, but double-check that this part of code can only run if it's in the same room that has a layer called "text_layer"
In the worst case, you may also try out instance_create_depth() and use the build-in depth variable from the object instead of the layer names. Using depth is more flexible, but less organised than layers.

Xamarin grid, column and row amounts

Hi im relatively new to c# code and i was wondering if there is any way to get the amount of columns and rows in a grid and store that amount in a variable
Something like:
var columnamount = grid.columnamount;
But i could not find anything that works
Thanks
You can use the following code to get a count of the columns and rows directly via the ColumnDefinitions and RowDefinitions properties. No need to enumerate the children of the grid because you may not have views in every column/row.
var columnCount = grid.ColumnDefintions.Count;
var rowCount = grid.RowDefinitions.Count;
For reference the documentation.
You might be able to do it this way, purely based on what I see in the docs:
var countColumns = grid.Children.Where( c => c.Column).Max();
var countRows = grid.Children.Where( c => c.Row).Max();
But I'm not sure if you can access Row anf Column properties on the child element.
This is not the best way to check, I guess, but it's working (same thing for columns):
EDIT: nope, for columns it doesn't work
int GetRowsCount(Grid grid)
{
var item = grid.Children.FirstOrDefault();
return item != null ? Grid.GetRow(item) + 1 : 0;
}

Java 7 => Java 8 : for to foreach on a Map with calculation

I begin with Java 8 and i have a migration project. I have read a lot of documentation and tutorial to use foreach or streams but i have a little last problem. I don't find the answer, just tutorial easy example.
I'm trying to transform this loop :
for ( Map.Entry<Neuron, Double> entry: this.entries.entrySet() ) {
value += entry.getKey().getExitValue() * entry.getValue();
}
This solution doesn't match and i know why (anonymous class => final/local var)
this.entries.forEach( (neuron, weight) -> {
value += neuron.getExitValue() * weight;
});
But only with a foreach i don't know how do this simple operation.
I think it's very easy but...
I have try with stream but i have similar problems.
Double sum = entries.entrySet()
.stream()
.forEach( entry-> { ? } );
Thanks you in advance.
As #Holger said in the comments above - in this case it is better to use mapToDoble. However there is still a way to do it using forEach loop. Please note that it is an ugly, dirty trick and it is just for demonstration purposes and it shouldn't be used in production code. As we know only final or effectively final variables can be used with lambda expressions, that's why value += is an illegal expression. Java-8 added a few new classes to java.util.concurrent.atomic one of them is DoubleAdder. You can use it with lambda:
DoubleAdder adder = new DoubleAdder();
stream.forEach(e -> adder.add(e.getKey().getExitValue() * e.getValue()));
System.out.println(adder.sum());
I don't see any cases when this should be used instead of mapToDouble
I introduced a list to stall the values and then do calculation with list.
final List<BigDecimal> valuesList = new ArrayList<>();
otherList.stream().forEach(val-> valuesList.add(map.get(val)));
final BigDecimal lastValue = valuesList.stream().filter(Objects::nonNull).reduce(BigDecimal.ZERO,BigDecimal::add);

Flex-Sorting on ArrayCollection

I have an ArrayCollection(neList) of Objects(neObj). Each neObj has several fields like ipAddress,TID,etc.. In most cases neObj will be have values of both TID and ipAddress, rarely it will not have TID but have ipAddress... After adding Objects(neObj), I need to sort the ArrayCollection whose behaviour must be similar to array.sort() which has got strings only..(i.e nos first followed by strings in alphabetical order)
Things I have tried:
1)Using neList.source.sort() and neList.refresh.. but it did not work as neList.source has objects not straight forward things like strings
2)I think i cannot use sortOn function of ArrayCollection as it can be done on only 1 field
My Requirement:
Use Case1:- Objects in ArrayCollection have both TID and IP
neObj1.TID="RAPC" neObj1.ipAddress="121.1.1.2"; neObj2.TID="RAPA" neObj2.ipAddress="121.1.1.1"
O/P after sorting should be
neObj2 neObj1
Use Case2:- 1 of the objects does not have TID
neObj1.ipAddress="121.1.1.2"; neObj2.TID="RAPA" neObj2.ipAddress="121.1.1.1"
O/P after sorting should be
neObj1 neObj2
As hinted in the comments, you'll need to use a sort compareFunction to decide how the items will be sorted.
I do like to point out that sorting a combination of letters and numbers is tricky in the sense that there is no natural order by default. e.g. when sorting, 1, 2 and 11, the order will be 1, 11, 2. You can however solve this using the naturalCompare method in the AS3Commons Lang project.
Here's a code sample for your case. The sort is implemented as a subclass of the Sort class so that you can easily reuse it in other collections:
package {
import mx.collections.Sort;
import org.as3commons.lang.StringUtils;
public class NaturalSort extends Sort {
public function NaturalSort() {
compareFunction = function (a:Object, b:Object, fields:Array = null):int {
var stringA:String = (("TID" in a) ? a.TID : "AAAA") + a.ipAddress;
var stringB:String = (("TID" in b) ? b.TID : "AAAA") + b.ipAddress;
return StringUtils.naturalCompare(stringA, stringB);
};
}
}
}
To apply this:
var collection:ArrayCollection;
collection.sort = new NaturalSort();
collection.refresh();

FLEX XMLDecoder turns `09.00` to "09.00", but `10.00` to 10

Could someone explain why the FLEX 4.5 XMLDecoder does this to my XML-data?
var decoder:XMLDecoder = new XMLDecoder;
var $object:Object = decoder.decode( <xmltag>08.00</xmltag> );
// object = "08.00"
var decoder:XMLDecoder = new XMLDecoder;
var $object:Object = decoder.decode( <xmltag>11.00</xmltag> );
// Object = "11" (HEY! Where did my '.00' part of the string go?)
var decoder:XMLDecoder = new XMLDecoder;
var $object:Object = decoder.decode( <xmltag>11.30</xmltag> );
// Object = "11.3" (HEY! Where did my '0' part of the string go?)
The Flex deserializer also gave me issues with this. It may be interpreting them as Number objects and thus they will return short representations when toString() is called.
Try using .toFixed(2) whenever you need to print a value such as 11.00
var $object:Object = decoder.decode( <xmltag>11.00</xmltag> );
trace($object); //11
trace($object.toFixed(2)); //11.00
So, to the answer the original question of why this is happening:
In the source code for SimpleXMLDecoder (which I'm guessing has similar functionality to XMLDecoder), there's a comment in the function simpleType():
//return the value as a string, a boolean or a number.
//numbers that start with 0 are left as strings
//bForceObject removed since we'll take care of converting to a String or Number object later
numbers that start with 0 are left as strings - I guess they thought of phone numbers but not decimals.
Also, because of some hacky implicit casting, you actually have three different types -
"0.800" : String
11 : int
11.3: Number

Resources