sortOn():试图对数组的副本进行排序,但原始数组也在排序中
sortOn(): Trying to sort the copy of an array, but the original is also being sorted
我正在尝试对数组的副本进行排序,但由于某种原因,两个数组都在排序。可能是什么原因造成的?
var myArray = [["stuff," "stuff"], ["stuff", "stuff"]]
var myArrayCopy = myArray as Array
trace(myArray) //Gives unsorted array
trace(myArrayCopy) //Gives unsorted array
arrayCopy.sortOn(1, Array.CASEINSENSITIVE)
trace(myArray) //Gives sorted array
trace(myArrayCopy) //Gives sorted array
在AS3中,简单来说,有两种类型的数据:primitive (int, uint, Number 、Boolean、String)和对象(其他所有内容,甚至是基本的 Object 和数组 类型)。原始数据按其值复制:
var a:int = 1;
var b:int;
// Now we pass the value of a.
b = a;
a = 2;
trace(a); // output: 2
trace(b); // output: 1
然后,所有对象都通过它们的引用传递(就像 C/C++ 语言中的指针),因此只有一个对象的原始实例和对它的多个引用:
var A:Array = [1, 2];
var B:Array;
// Now we pass the reference to the A.
B = A;
A[0] = 2;
trace(A); // output: 2,2
trace(B); // output: 2,2
为了复制对象数据,您需要有一点了解。有 DodgerThud mentioned, deep copy and shallow copy 项。简单地说,shallow copy 创建顶层容器的克隆,同时按原样复制更深层次。 deep 副本将所有内容克隆到底部,因此无论您对另一个副本做什么,一个副本都不会受到任何影响。
浅拷贝一个数组:
var A:Array = [1,2,[3]];
var B:Array;
// Make a shallow copy.
B = A.slice();
// Lets change the original and see.
A[0] = 2;
A[1] = 3;
A[2][0] = 4;
trace(A); // output: 2,3,4
trace(B); // output: 1,2,4
因此,A 和 B 是不同的 Arrays,但它们的最后一个元素引用相同的 Array.
浅拷贝一个对象:
var A:Object = {a:1,b:2,c:[3]};
var B:Object;
// Make a shallow copy.
B = new Object;
// Iterate over keys in A.
for (var aKey:String in A)
{
// Copy members of A one by one.
B[aKey] = A[aKey];
}
// Let's change the original and see.
A.a = 2;
A.b = 3;
A.c[0] = 4;
trace(A.a, A.b, A.c); // output: 2 3 4
trace(B.a, B.b, B.c); // output: 1 2 4
然后,深拷贝。通常,您递归地遍历顶级对象及其所有后代,以确保每个数据和任何数据都作为副本而不是对原始数据的引用。同时注意重复条目和循环引用。
然而(幸运的是)在 AS3 中有一些快捷方式。您可以通过 ByteArray 进行深度复制。这将(经过测试和确认)可以很好地处理重复和循环引用:
function deepCopy(source:*):*
{
var BA:ByteArray = new ByteArray;
BA.writeObject(source);
BA.position = 0;
var result:* = BA.readObject();
BA.clear();
return result;
}
var A:Array = [1, 2, [3]];
var B:Array = deepCopy(A);
// Let's change the original and see.
A[0] = 2;
A[1] = 3;
A[2][0] = 4;
trace(A); // output: 2,3,4
trace(B); // output: 1,2,3
不确定它是否会以任何方式更快、更好或更优化,但仍然是另一种方式:
function deepCopy(source:*):*
{
return JSON.parse(JSON.stringify(source));
}
对他们两个都有一些见解。
JSON深拷贝:
- 重复:否(将它们克隆为不同的对象)
- 循环引用:无(运行时错误)
- 自定义 classes: 否
- 支持的数据类型:int、uint、Number、Boolean、String、Object、Array
ByteArray深拷贝:
- 重复:是
- 循环引用:是
- 自定义classes:通过registerClassAlias方法
- 支持的数据类型:int、uint、Number、Boolean、String、Object、Array、ByteArray
这是我自己的 deepCopy 版本:
private const SIMPLE:Object =
{
"number":true,
"string":true,
"boolean":true,
"undefined":true
};
private const XNODE:String = getQualifiedClassName(XML);
private const XLIST:String = getQualifiedClassName(XMLList);
private const ARRAY:String = getQualifiedClassName(Array);
private const OBJECT:String = getQualifiedClassName(Object);
private const BYTES:String = getQualifiedClassName(ByteArray);
private var lock:Dictionary;
private function deepCopy(source:*):*
{
// Handle primitive data.
if (source == null) return source;
if (source is Class) return source;
if (SIMPLE[typeof(source)]) return source;
var result:*;
var aLock:Boolean;
var aQname:String;
if (!lock)
{
// If we're here, then we're at the top level
// so we should devise cache for handling
// duplicates and circular references.
lock = new Dictionary;
aLock = true;
}
// If it is cached, then it is either
// duplicate or circular reference.
if (lock[source]) return lock[source];
aQname = getQualifiedClassName(source);
if (aQname == BYTES)
{
var aBytes:ByteArray;
aBytes = new ByteArray;
aBytes.writeBytes(source, 0, source.length);
result = aBytes;
lock[source] = result;
}
else if (aQname == ARRAY)
{
var aRay:Array;
aRay = new Array;
aRay.length = source.length;
result = aRay;
lock[source] = result;
// Copy the elements of the source Array one by one.
for (var i:int = 0; i < aRay.length; i++)
{
aRay[i] = deepCopy(source[i]);
}
}
else if (aQname == OBJECT)
{
var aRes:Object;
aRes = new Object;
result = aRes;
lock[source] = result;
// Copy the members of the source Object one by one.
for (var aKey:String in source)
{
aRes[aKey] = deepCopy(source[aKey]);
}
}
else if ((aQname == XNODE) || (aQname == XLIST))
{
// This one is tricky. The object to clone might
// have a reference to some descendant node of some
// big XML. There could be several references to
// different sub-nodes either. Probably you should
// not rely on this method to clone XML data unless
// you are totally aware of what you are doing.
result = source.copy();
lock[source] = result;
}
else
{
// If we're here, that means that source holds
// a reference to some class instance. You should
// define here your own ways to handle them.
result = source;
}
if (aLock)
{
// If we're here, then we're at the top level
// so we should do some clean-up before we leave.
for (var aRef:* in lock)
{
delete lock[aRef];
}
lock = null;
}
return result;
}
自定义深拷贝:
- 重复:是
- 循环引用:是
- 自定义 classes:您应该定义自己的处理规则
- 支持的数据类型:int、uint、Number、Boolean、String、Object、Array、ByteArray、XML(有限)、class 构造函数
我正在尝试对数组的副本进行排序,但由于某种原因,两个数组都在排序。可能是什么原因造成的?
var myArray = [["stuff," "stuff"], ["stuff", "stuff"]]
var myArrayCopy = myArray as Array
trace(myArray) //Gives unsorted array
trace(myArrayCopy) //Gives unsorted array
arrayCopy.sortOn(1, Array.CASEINSENSITIVE)
trace(myArray) //Gives sorted array
trace(myArrayCopy) //Gives sorted array
在AS3中,简单来说,有两种类型的数据:primitive (int, uint, Number 、Boolean、String)和对象(其他所有内容,甚至是基本的 Object 和数组 类型)。原始数据按其值复制:
var a:int = 1;
var b:int;
// Now we pass the value of a.
b = a;
a = 2;
trace(a); // output: 2
trace(b); // output: 1
然后,所有对象都通过它们的引用传递(就像 C/C++ 语言中的指针),因此只有一个对象的原始实例和对它的多个引用:
var A:Array = [1, 2];
var B:Array;
// Now we pass the reference to the A.
B = A;
A[0] = 2;
trace(A); // output: 2,2
trace(B); // output: 2,2
为了复制对象数据,您需要有一点了解。有 DodgerThud mentioned, deep copy and shallow copy 项。简单地说,shallow copy 创建顶层容器的克隆,同时按原样复制更深层次。 deep 副本将所有内容克隆到底部,因此无论您对另一个副本做什么,一个副本都不会受到任何影响。
浅拷贝一个数组:
var A:Array = [1,2,[3]];
var B:Array;
// Make a shallow copy.
B = A.slice();
// Lets change the original and see.
A[0] = 2;
A[1] = 3;
A[2][0] = 4;
trace(A); // output: 2,3,4
trace(B); // output: 1,2,4
因此,A 和 B 是不同的 Arrays,但它们的最后一个元素引用相同的 Array.
浅拷贝一个对象:
var A:Object = {a:1,b:2,c:[3]};
var B:Object;
// Make a shallow copy.
B = new Object;
// Iterate over keys in A.
for (var aKey:String in A)
{
// Copy members of A one by one.
B[aKey] = A[aKey];
}
// Let's change the original and see.
A.a = 2;
A.b = 3;
A.c[0] = 4;
trace(A.a, A.b, A.c); // output: 2 3 4
trace(B.a, B.b, B.c); // output: 1 2 4
然后,深拷贝。通常,您递归地遍历顶级对象及其所有后代,以确保每个数据和任何数据都作为副本而不是对原始数据的引用。同时注意重复条目和循环引用。
然而(幸运的是)在 AS3 中有一些快捷方式。您可以通过 ByteArray 进行深度复制。这将(经过测试和确认)可以很好地处理重复和循环引用:
function deepCopy(source:*):*
{
var BA:ByteArray = new ByteArray;
BA.writeObject(source);
BA.position = 0;
var result:* = BA.readObject();
BA.clear();
return result;
}
var A:Array = [1, 2, [3]];
var B:Array = deepCopy(A);
// Let's change the original and see.
A[0] = 2;
A[1] = 3;
A[2][0] = 4;
trace(A); // output: 2,3,4
trace(B); // output: 1,2,3
不确定它是否会以任何方式更快、更好或更优化,但仍然是另一种方式:
function deepCopy(source:*):*
{
return JSON.parse(JSON.stringify(source));
}
对他们两个都有一些见解。
JSON深拷贝:
- 重复:否(将它们克隆为不同的对象)
- 循环引用:无(运行时错误)
- 自定义 classes: 否
- 支持的数据类型:int、uint、Number、Boolean、String、Object、Array
ByteArray深拷贝:
- 重复:是
- 循环引用:是
- 自定义classes:通过registerClassAlias方法
- 支持的数据类型:int、uint、Number、Boolean、String、Object、Array、ByteArray
这是我自己的 deepCopy 版本:
private const SIMPLE:Object =
{
"number":true,
"string":true,
"boolean":true,
"undefined":true
};
private const XNODE:String = getQualifiedClassName(XML);
private const XLIST:String = getQualifiedClassName(XMLList);
private const ARRAY:String = getQualifiedClassName(Array);
private const OBJECT:String = getQualifiedClassName(Object);
private const BYTES:String = getQualifiedClassName(ByteArray);
private var lock:Dictionary;
private function deepCopy(source:*):*
{
// Handle primitive data.
if (source == null) return source;
if (source is Class) return source;
if (SIMPLE[typeof(source)]) return source;
var result:*;
var aLock:Boolean;
var aQname:String;
if (!lock)
{
// If we're here, then we're at the top level
// so we should devise cache for handling
// duplicates and circular references.
lock = new Dictionary;
aLock = true;
}
// If it is cached, then it is either
// duplicate or circular reference.
if (lock[source]) return lock[source];
aQname = getQualifiedClassName(source);
if (aQname == BYTES)
{
var aBytes:ByteArray;
aBytes = new ByteArray;
aBytes.writeBytes(source, 0, source.length);
result = aBytes;
lock[source] = result;
}
else if (aQname == ARRAY)
{
var aRay:Array;
aRay = new Array;
aRay.length = source.length;
result = aRay;
lock[source] = result;
// Copy the elements of the source Array one by one.
for (var i:int = 0; i < aRay.length; i++)
{
aRay[i] = deepCopy(source[i]);
}
}
else if (aQname == OBJECT)
{
var aRes:Object;
aRes = new Object;
result = aRes;
lock[source] = result;
// Copy the members of the source Object one by one.
for (var aKey:String in source)
{
aRes[aKey] = deepCopy(source[aKey]);
}
}
else if ((aQname == XNODE) || (aQname == XLIST))
{
// This one is tricky. The object to clone might
// have a reference to some descendant node of some
// big XML. There could be several references to
// different sub-nodes either. Probably you should
// not rely on this method to clone XML data unless
// you are totally aware of what you are doing.
result = source.copy();
lock[source] = result;
}
else
{
// If we're here, that means that source holds
// a reference to some class instance. You should
// define here your own ways to handle them.
result = source;
}
if (aLock)
{
// If we're here, then we're at the top level
// so we should do some clean-up before we leave.
for (var aRef:* in lock)
{
delete lock[aRef];
}
lock = null;
}
return result;
}
自定义深拷贝:
- 重复:是
- 循环引用:是
- 自定义 classes:您应该定义自己的处理规则
- 支持的数据类型:int、uint、Number、Boolean、String、Object、Array、ByteArray、XML(有限)、class 构造函数