(Ceci est une question de coldfusion)
J'ai deux structures différentes pouvant contenir ou non les mêmes données, et je veux pouvoir voir s'ils le font! Mes structures contiendront toujours des valeurs simples (chiffres, cordes ou booléens) car ils sont créés avec DESERIALIZONJSON, alors j'espère que cela peut être fait facilement. P>
J'ai trouvé le message de Ben Nadel ici , mais cette technique ne semble pas fonctionner pour moi. Voici ce que j'ai essayé jusqu'à présent (un code CFWheels de là): p> et les résultats à qui ressemble: p> Donc, comme vous le verrez ci-dessus, bien que les données à l'intérieur des structures semblent correspondre exactement, elles ne transmettent pas le test Equals (). P> Quelqu'un d'autre a-t-il fait avec succès? p> p>
6 Réponses :
Voici la solution de Ben est rapidement ajustée à mes besoins, vous pouvez l'ajuster plus loin (et espérons-y le faire préserver):
<cffunction name="DiffStructs" hint="Compute the differences between two structures" access="public" output="true" returntype="array" > <cfargument name="First" type="struct" required="true" /> <cfargument name="Second" type="struct" required="true" /> <cfargument name="ignoreMissing" type="boolean" required="false" default="false" /> <cfargument name="ignoreFirstEmptyString" type="boolean" required="false" default="false" /> <cfargument name="ignoreSecondEmptyString" type="boolean" required="false" default="false" /> <cfset var Result = arrayNew(1) > <cfset var Keys = structNew() > <cfset var KeyName = "" > <cfset var obj = "" > <cfset var firstOk = true > <cfset var secondOk = true > <cfloop collection="#Arguments.First#" item="KeyName"> <cfset Keys[KeyName]=1> </cfloop> <cfloop collection="#Arguments.Second#" item="KeyName"> <cfset Keys[KeyName]=1> </cfloop> <cfloop collection="#Keys#" item="KeyName"> <cfif NOT StructKeyExists(Arguments.First, KeyName) > <cfif NOT arguments.ignoreMissing> <cfif structFind(Arguments.Second, KeyName) neq ""> <cfif arguments.ignoreSecondEmptyString> <cfset obj = { key = KeyName ,old = "" ,new = structFind(Arguments.Second, KeyName) } > <cfset arrayAppend(Result, obj )> </cfif> </cfif> </cfif> <cfelseif NOT StructKeyExists(Arguments.Second, KeyName)> <cfif NOT arguments.ignoreMissing> <cfif structFind(Arguments.First, KeyName) neq ""> <cfif arguments.ignoreFirstEmptyString > <cfset obj = { key = KeyName ,old = structFind(Arguments.First, KeyName) ,new = "" } > <cfset arrayAppend(Result, obj )> </cfif> </cfif> </cfif> <cfelseif Arguments.First[KeyName] NEQ Arguments.Second[KeyName] > <cfset firstOk = true > <cfset secondOk = true > <cfif structFind(Arguments.Second, KeyName) eq ""> <cfif arguments.ignoreSecondEmptyString> <cfset firstOk = false > </cfif> </cfif> <cfif structFind(Arguments.First, KeyName) eq ""> <cfif arguments.ignoreFirstEmptyString> <cfset secondOk = false > </cfif> </cfif> <cfif firstOk AND secondOk > <cfset obj = { key = KeyName ,old = structFind(Arguments.First, KeyName) ,new = structFind(Arguments.Second, KeyName) } > <cfset arrayAppend(Result, obj )> </cfif> </cfif> </cfloop> <cfreturn Result> </cffunction>
Merci pour la réponse rapide - c'est très proche de ce dont j'ai besoin!
Je pense que vous voulez non arguments.ignorefirStyring code> sur les lignes 25 et
non arguments.ignoreecondemptyString code> à la ligne 37. Comme si une clé existe dans une structure mais non dans l'autre, elle sera ne pas être retourné. Si vous utilisez le
pas code>, il retournera la clé si elle est dans une structure et non l'autre.
Si vous utilisez cf9 ou Railo 3
ArrayFindNoCase([struct1], struct2)); //case-insensitive, 0 if not the same. ArrayContainsNoCase([struct1], struct2); // if you use Railo
super info. Bien que j'essayais de faire un simple vrai ou faux comparer dans ma question, la matrice DIFF générée par la fonction de Zarko a inspiré une modification de mon interface qui offrira une fonctionnalité beaucoup plus utile. Je pourrais utiliser l'un d'entre eux pour effectuer une vérification initiale avant d'exécuter la diffusion complète, cependant.
caché dans les structures de coldfusion est une petite méthode pratique appelée hashcode (). Bien que ce soit à l'esprit que cela est sans papiers.
Nope, je viens de l'essayer sur Railo et la valeur Hashcode est toujours différente. Bien que ... ST1.TOSTRING () EQ ST2.TOSTRING () fonctionne sur RAILO;)
Vous pouvez également effectuer cela à l'aide de la méthode Java natif héritée par le CFC.
isThisTrue = ObjA.equals(ObjB);
Notez que c'est la technique que j'ai démontrée dans le poste initial. Avec mes deux autres structs apparaissant semblables, il donne "faux". Equals () ne fonctionne pas dans tous les cas.
Voici quelque chose que j'ai jeté ensemble. Il a un paramètre pour déterminer s'il faut ou non une comparaison sensible à la casse des valeurs et des clés. Jeter ces deux fonctions ( limitation forte>: ne fonctionne pas pour STRUCTIONS / TAREILS contenant des requêtes ou des objets. P> structure () code>,
arrayequaux () code>) dans une sorte d'utilitaires cfc.
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]));
}
if(serializeJSON(itemA) eq serializeJSON(itemB)) //They match! else //They don't! You are already using JSON to manipulate these, you should just keep with that. Not that anyone cares a decade later, but that method works for me.
hmm .. Typo? "Cause" Numéro d'identification 70634 "et" IDNumber 70634 "ne sont pas les mêmes