JeuWeb - Crée ton jeu par navigateur
[PHP] Fusion d'un tableau par addition - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : [PHP] Fusion d'un tableau par addition (/showthread.php?tid=2142)

Pages : 1 2 3 4 5 6


RE: [PHP] Fusion d'un tableau par addition - srm - 19-03-2011

Et puis un petit exemple en Scala pour le fun

// Un import, pas besoin d'explication non ? :)
import scala.collection.mutable.HashMap

// La classe principale qui sert à exécuter le test
object Test {

// Une classe que je créer pour étendre le type de base HashMap
// afin d'y ajouter un nouveau type de "somme" de tableau
// et l'argument quelle prend à la construction,
// ici HashMap[String, Int] est mon type de tableau associatif, qui a des strings en tant que clé, et des int en tant que valeur
class HashMapImproved(hm: HashMap[String, Int]) {

// ici le nom de ma méthode un peu chelou "++=" oui oui lol
// ma fonction a comme argument une variable hm2 du type HashMap[String, Int]
// elle va retourner un HashMap[String, Int]
def +++= (hm2: HashMap[String, Int]): HashMap[String, Int] = {
// Pas besoin d'explication je pense, c'est un genre de foreach :)
for ((key,value) <- hm2) {
// si hm (ma variable de classe, voir plus haut dans la définition de ma classe) contient la clé
// j'ajoute sa valeur à l'actuelle, sinon je l'assigne directement
if (hm.contains(key)) {
hm(key) += value
} else {
hm(key) = value
}
}
// je retourne l'objet du coup
hm
}
}

// Donc ici la méthode principale qui va être exécuté pour faire les tests
def main(args: Array[String]) {

// Ca c'est un petit truc magique que l'on peut appeler un peu partout
// tous les objets du type HashMap vont être automatiquement convertis en objet du type
// HashMapImproved :)
implicit def convertHashMap2HashMapImproved(hm: HashMap[String, Int]) = new HashMapImproved(hm)

// Déclaration de mes variables de test
val array1 = new HashMap[String, Int]
val array2 = new HashMap[String, Int]
val array3 = new HashMap[String, Int]

// Remplissage de mes tableaux
array1 += ("nb_cerises" -> 2, "nb_bananes" -> 2, "nb_poires" -> 5)
array2 += ("nb_cerises" -> 100, "nb_choux" -> 20)
array3 += ("nb_tomates" -> 30, "nb_bananes" -> 20)

// Hop j'ajoute le tableau array1 au tableau array2
array2 +++= array1

// J'affiche le résultat
for ((key, value) <- array2) {
println(key + " : " + value)
}

println("-")

// J'ajoute le tableau array3 au tableau array2
array2 +++= array3

// J'affiche le résultat
for ((key, value) <- array2) {
println(key + " : " + value)
}

}
}


nb_poires : 5
nb_choux : 20
nb_bananes : 2
nb_cerises : 102
-
nb_poires : 5
nb_choux : 20
nb_bananes : 22
nb_tomates : 30
nb_cerises : 102

Je l'ai fait un peu à l'arrachage, ça fait bien 6 mois que je n'avais pas touché une ligne de Scala :D


RE: [PHP] Fusion d'un tableau par addition - niahoo - 19-03-2011

Arf bon du coup ça m'a donné envie de le faire en erlang. c'était marrant mais il faut savoir avant toute chose que ce n'est pas du tout adapté à ce langage. Erlang est bien en dessous de php pour la gestion de tels tableaux.


%%% pour Jeuweb
-module(php_array_add).

%%% Utils
-export([array_add/1]).

%%% Tests
-export([test/0]).

test() ->
Array1 = [{trucs, 12},{machins, 3},{choses, -4}],
Array2 = [{machins, 1},{choses, 80}, {'FAIL!', "pas un int()"}],
Array3 = [{machins, 12},{bidules, 24},{trucs, "ici non plus"}],
array_add([Array1, Array2, Array3]).

%% Si un seul tableau est passé on le retourne
array_add([Ar|[]]) -> Ar;

%% Quand il ne reste que 2 tableaux à traiter, on renvoie leur "somme"
array_add([A1, A2|[]]) -> addition(A1,A2);

%% ici on pioche les deux premiers tableaux de la liste
%% et on repose leur "somme" sur la liste
array_add([A1, A2|Arrays]) -> array_add([addition(A1,A2)|Arrays]).


%% ici on se sert d'un accumulateur Acc, il joue le rôle de $result
addition(A1, A2) -> addition(A1, A2, []).

%% cette fonction n'est pas du tout performante, c'est pour l'exemple,
%% ici on parcourt maintes fois A2, bien plus que nécessaire
addition([], A2, Acc) -> A2 ++ Acc;
addition([{Key, Value}|A1], A2, Acc) when is_integer(Value)->

ToAdd = case proplists:get_value(Key, A2, 0) of
X when is_integer(X) -> X;
_ -> 0
end,

NewPair = {Key, Value + ToAdd},
addition(A1, proplists:delete(Key, A2), [NewPair|Acc]);

%% Si la value n'est pas un entier, j'ai pris comme parti de la zapper
addition([{_Key, _Value}|A1], A2, Acc) -> addition(A1, A2, Acc).



29> c(php_array_add).
{ok,php_array_add}
30> php_array_add:test().
[{bidules,24},{trucs,12},{machins,16},{choses,76}]
31>

Version avec des dicts

-module(jeuweb).
-export([dict_melt/1,test/0,add_only_int/3]).

dict_melt([]) ->
dict:new();
dict_melt([Dict|[]]) ->
dict:to_list(Dict);
dict_melt([Dict1,Dict2|Dicts]) ->
dict_melt([melt(Dict1,Dict2)|Dicts]).

melt(D1,D2) ->
dict:merge(fun(K,V,VV)->add_only_int(K,V,VV) end, D1, D2).

add_only_int(_K, V1, V2) when is_integer(V1), is_integer(V2) ->
V1 + V2;
add_only_int(_K, V1, _V2) when is_integer(V1) -> V1;
add_only_int(_K, _V1, V2) when is_integer(V2) -> V2.

test() ->
Arrays = [
[{trucs, 12},{machins, 3},{choses, -4}],
[{machins, 1},{choses, 80}, {'FAIL!', "pas un int()"}],
[{machins, 12},{bidules, 24},{trucs, "ici non plus"}]
],

dict_melt(lists:map(fun(L) -> dict:from_list(L) end, Arrays)).




RE: [PHP] Fusion d'un tableau par addition - srm - 19-03-2011

C'est "particulier" ^^


RE: [PHP] Fusion d'un tableau par addition - niahoo - 19-03-2011

avec la couleur c'est plus lisible :p


RE: [PHP] Fusion d'un tableau par addition - srm - 19-03-2011

Moui moui, je trouve la puissance de Scala plus sympa Wink


RE: [PHP] Fusion d'un tableau par addition - niahoo - 19-03-2011

Ah je ne cherchais pas la comparaison.

Je dirais que j'apprécie erlang pour sa simplicité. le langage est super simple, un peu chiant à écrire mais en deux semaines tu sais tout écrire. le framework qui va avec est plus long à maîtriser mais il n'est pas indispensable (bien que vivement conseillé !).

Ce que tu appelles puissance est un peu abstrait. Qu'entends tu pas la ?


RE: [PHP] Fusion d'un tableau par addition - srm - 19-03-2011

Et bien par exemple l'implicit cast ce qui te permet de créer et les possibilités de nom et la façon d'utiliser les fonctions.
Dans un autre langage on ferait :
array2.add(array1)
Dans Scala on peut faire :
array2 add array1
Et on peut faire encore mieux car Scala autorise quasiment tout comme caractère en nom de fonction :
array2 + array1

Ce qui rend le tout très sexy Smile

Et bien sûr on peut faire ça sans avoir à surcharger la classe HashMap grâce au implicit cast qui va automatiquement convertir un objet HashMap en HashMapImproved Smile


RE: [PHP] Fusion d'un tableau par addition - niahoo - 19-03-2011

Hmm les trucs implicites c'est un nid à bugs je trouve (enfin, le cast, virer les parenthèses des appels de fonctions ça c'est cool).
edit : je reconnais que c'est pratique et élégant, mais j'aime pas. du code verbeux ne me dérange pas, surtout quand on voit le nombre de lignes très petit des programmes erlang.
(ici l'exemple n'est pas adapté)

je suppose que tu pouvais faire " array2 +++= array1 +++= array3 "
ça donne
[array2.+++=(array1).+++=(array3)]
ou bien
[array2.+++=(array1.+++=(array3))]


J'ai le sentiment qu'on peut facilement se paumer dans son code avec tout ça. Erlang est à l'opposé, tout est clair (mis à part les records,des genres de struct C mais implémentées via un raccourci de compilation, un syntaxic sugar pas si sugar que ça).

Quand tu parlais de puissance, je croyais que tu parlais des possibilités offertes par le langage. J'ai testé scala quand tu m'avais fait passer un document, j'avais commencé à m'y mettre et j'ai croisé erlang qui m'a plus plu, par la simplicité et il dispose du même modèle de message passing sauf qu'il n'y a pas d'objets, il y a simplement des fonctions.

Il y a aussi les serveurs, qui sont finalement l'équivalent des objets.

par serveur j'entends la fonction avec un receive qui s'appelle récursivement à l'infini mais dans un modèle "officiel" plus général et bien fichu, et simplissime.


Personne n'a une implémentation dans un autre langage ? ça peut être intéressant.


RE: [PHP] Fusion d'un tableau par addition - srm - 19-03-2011

Oui sauf que là c'est implicite seulement si tu lui a spécifiquement demandé :
implicit def convertHashMap2HashMapImproved(hm: HashMap[String, Int]) = new HashMapImproved(hm)

Donc tu sais ce que tu demandes Wink
De plus tu peux demander ce fonctionnement implicite dans le scope que tu veux.
Ça peut-être à l'import du fichier (si tu le mets dans un fichier externe) dans ta main class, dans un if, ou tu veux.

Et c'est une fonction très puissante cet implicite cast à la demande.

Je n'ai pas parlé de mon exemple en disant que c'était mon verbeux, mais en montrant pourquoi c'était plus "propre" et "élégant".
Je m'en moque aussi que ça soit verbeux Smile

Et non tu ne peux pas faire array +++= array1 +++= array3 Smile

Et je ne vois pas ce qu'il y a de pas clair à faire :
array1 ++= array2
Tu vois bien que tu ajoutes deux tableaux, mais que ça n'est pas une addition banale vu que tu as ++=
Pour respecter un peu le système de Ruby j'aurais très bien pu faire une fonction genre :
array1 mergeWithSum! array2

Et je parle au niveau puissance en effet des possibilités offertes par le langage, vu qu'ici ça n'est qu'un exemple et j'en ai déjà donné plusieurs Wink

Sinon je serais curieux moi aussi de voir ce que l'on peut faire dans les autres langage Smile


RE: [PHP] Fusion d'un tableau par addition - niahoo - 19-03-2011

J'ai simplement peur que quand tu partages du code avec quelqu'un d'autre, les trucs implicites déclarés dans n'importe quel scope seront difficiles à déceler.

edit : sinon, array2 +++= array1 c'est très clair, j'ai bien dit que ce type d'appel implicite n'était pas un problème, j'ajouterais que j'aimerais bien que ça soit possible dans d'autres langages, en erlang ça donnerai du haskell, en php ça ferait du ruby et ça serait cool. mais (voir en dessous) si ça s'annule des qu'il faut mettre plus de un paramètre ou chainer, c'estdommage)

De plus, est-il possible d'appeler les méthodes du HashMap sur ton objet HashMapImproved que tu n'as pas redéfinies. Je suppose que oui donc ce n'est finalement pas un vrai problème, mais je sens que ça peut être gênant. (je "sens", tout ça est une question de feeling de toute façon)

ce que tu dis à propos de la verbosité est contradictoire, l'élégance et la verbosité en terme de code sont vraiment opposés

"Et non tu ne peux pas faire array +++= array1 +++= array3"

tu peux faire "array2.+++=(array1).+++=(array3)" je supose.

mais alors comment tu fais pour "additionner" non pas 2 mais 3 arrays ? (désolé si c'est évident, je ne l'ai pas lu, mais du coup enlever les parenthèses c'est bien beau mais si tu dois les remettre pour chaîner ça fait tache.