Oto coś, co rzuciłem szybko. Ma parametr określający, czy porównywać wartości i klucze, czy też nie. Wrzuć te dwie funkcje (StructEquals()
, ArrayEquals()
) do pewnego rodzaju narzędzi CFC.
Ograniczenie: Nie działa dla structs/arrays zawierających zapytania lub obiekty.
<cffunction name="StructEquals" access="public" returntype="boolean" output="false"
hint="Returns whether two structures are equal, going deep.">
<cfargument name="stc1" type="struct" required="true" hint="First struct to be compared." />
<cfargument name="stc2" type="struct" required="true" hint="Second struct to be compared." />
<cfargument name="blnCaseSensitive" type="boolean" required="false" default="false" hint="Whether or not values are compared case-sensitive." />
<cfargument name="blnCaseSensitiveKeys" type="boolean" required="false" default="false" hint="Whether or not structure keys are compared case-sensitive." />
<cfscript>
if(StructCount(stc1) != StructCount(stc2))
return false;
var arrKeys1 = StructKeyArray(stc1);
var arrKeys2 = StructKeyArray(stc2);
ArraySort(arrKeys1, 'text');
ArraySort(arrKeys2, 'text');
if(!ArrayEquals(arrKeys1, arrKeys2, blnCaseSensitiveKeys, blnCaseSensitiveKeys))
return false;
for(var i = 1; i <= ArrayLen(arrKeys1); i++) {
var strKey = arrKeys1[i];
if(IsStruct(stc1[strKey])) {
if(!IsStruct(stc2[strKey]))
return false;
if(!StructEquals(stc1[strKey], stc2[strKey], blnCaseSensitive, blnCaseSensitiveKeys))
return false;
}
else if(IsArray(stc1[strKey])) {
if(!IsArray(stc2[strKey]))
return false;
if(!ArrayEquals(stc1[strKey], stc2[strKey], blnCaseSensitive, blnCaseSensitiveKeys))
return false;
}
else if(IsSimpleValue(stc1[strKey]) && IsSimpleValue(stc2[strKey])) {
if(blnCaseSensitive) {
if(Compare(stc1[strKey], stc2[strKey]) != 0)
return false;
}
else {
if(CompareNoCase(stc1[strKey], stc2[strKey]) != 0)
return false;
}
}
else {
throw("Can only compare structures, arrays, and simple values. No queries or complex objects.");
}
}
return true;
</cfscript>
</cffunction>
<cffunction name="ArrayEquals" access="public" returntype="boolean" output="false"
hint="Returns whether two arrays are equal, including deep comparison if the arrays contain structures or sub-arrays.">
<cfargument name="arr1" type="array" required="true" hint="First struct to be compared." />
<cfargument name="arr2" type="array" required="true" hint="Second struct to be compared." />
<cfargument name="blnCaseSensitive" type="boolean" required="false" default="false" hint="Whether or not values are compared case-sensitive." />
<cfargument name="blnCaseSensitiveKeys" type="boolean" required="false" default="false" hint="Whether or not structure keys are compared case-sensitive, if array contains structures." />
<cfscript>
if(ArrayLen(arr1) != ArrayLen(arr2))
return false;
for(var i = 1; i <= ArrayLen(arr1); i++) {
if(IsStruct(arr1[i])) {
if(!IsStruct(arr2[i]))
return false;
if(!StructEquals(arr1[i], arr2[i], blnCaseSensitive, blnCaseSensitiveKeys))
return false;
}
else if(IsArray(arr1[i])) {
if(!IsArray(arr2[i]))
return false;
if(!ArrayEquals(arr1[i], arr2[i], blnCaseSensitive, blnCaseSensitiveKeys))
return false;
}
else if(IsSimpleValue(arr1[i]) && IsSimpleValue(arr2[i])) {
if(blnCaseSensitive) {
if(Compare(arr1[i], arr2[i]) != 0)
return false;
}
else {
if(CompareNoCase(arr1[i], arr2[i]) != 0)
return false;
}
}
else {
throw("Can only compare structures, arrays, and simple values. No queries or complex objects.");
}
}
return true;
</cfscript>
</cffunction>
Jednostka Testy dla wszystkich zainteresowanych:
public void function test_StructEquals() {
AssertTrue(utils.StructEquals({}, StructNew()));
AssertTrue(utils.StructEquals({}, StructNew(), true, true));
AssertFalse(utils.StructEquals({}, {"a": "b", "c": "d"}));
AssertTrue(utils.StructEquals({"a": "b", "c": "d"}, {"C": "D", "A": "B"}));
AssertFalse(utils.StructEquals({"a": "b", "c": "d"}, {"C": "D", "A": "B"}, true, false));
AssertFalse(utils.StructEquals({"a": "b", "c": "d"}, {"C": "D", "A": "B"}, false, true));
AssertTrue(utils.StructEquals({"a": "b", "c": "d"}, {"C": "d", "A": "b"}));
AssertTrue(utils.StructEquals({"a": "b", "c": "d"}, {"C": "d", "A": "b"}, true, false));
AssertFalse(utils.StructEquals({"a": "b", "c": "d"}, {"C": "d", "A": "b"}, false, true));
AssertTrue(utils.StructEquals({"a": "b", "c": "d"}, {"c": "D", "a": "B"}));
AssertFalse(utils.StructEquals({"a": "b", "c": "d"}, {"c": "D", "a": "B"}, true, false));
AssertTrue(utils.StructEquals({"a": "b", "c": "d"}, {"c": "D", "a": "B"}, false, true));
var stc1 = {
"test": {
"hello": "world",
"goodbye": "space",
"somearr": [
{ "a": 1, "b": 2 },
"WORD",
[
{ "x": 97, "y": 98, "z": 99 },
{ "i": 50, "j": 51, "k": 52 }
]
]
}
};
var stc2 = {
"test": {
"goodbye": "space",
"hello": "world",
"somearr": [
{ "a": 1, "b": 2 },
"WORD",
[
{ "z": 99, "x": 97, "y": 98 },
{ "i": 50, "k": 52, "j": 51 }
]
]
}
};
AssertTrue(utils.StructEquals(stc1, stc2, true, true));
stc2.test.somearr[2] = "WOrD";
AssertTrue(utils.StructEquals(stc1, stc2));
AssertTrue(utils.StructEquals(stc1, stc2, false, true));
AssertFalse(utils.StructEquals(stc1, stc2, true, false));
stc2.test.somearr[3][1] = { "z": 99, "X": 97, "y": 98 };
AssertTrue(utils.StructEquals(stc1, stc2));
AssertFalse(utils.StructEquals(stc1, stc2, false, true));
AssertFalse(utils.StructEquals(stc1, stc2, true, false));
stc2.test.somearr[2] = "WORD";
AssertTrue(utils.StructEquals(stc1, stc2));
AssertFalse(utils.StructEquals(stc1, stc2, false, true));
AssertTrue(utils.StructEquals(stc1, stc2, true, false));
}
public void function test_ArrayEquals() {
AssertTrue(utils.ArrayEquals([], ArrayNew(1)));
AssertTrue(utils.ArrayEquals([], ArrayNew(1), true, true));
AssertFalse(utils.ArrayEquals([], [1, 2, 3]));
AssertTrue(utils.ArrayEquals(['a', 'b', 'c'], ['A', 'B', 'C']));
AssertFalse(utils.ArrayEquals(['a', 'b', 'c'], ['A', 'B', 'C'], true, false));
AssertTrue(utils.ArrayEquals(['a', 'b', 'c'], ['A', 'B', 'C'], false, true));
AssertFalse(utils.ArrayEquals(['a', 'b', 'c'], ['a', 'c', 'b']));
AssertTrue(utils.ArrayEquals([1, 2, 3], [1, 2, 3]));
AssertFalse(utils.ArrayEquals([1, 2, 3], [1, 3, 2]));
}
hmm .. literówka? "przyczyna" nr id 70634 "i" idnumber 70634 "to nie to samo – Henry
tak, to był rzeczywiście literówka! –