JeuWeb - Crée ton jeu par navigateur
[Résolu] Transformer un couple clé/valeur en hash imbriqués - 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 : [Résolu] Transformer un couple clé/valeur en hash imbriqués (/showthread.php?tid=5616)



[Résolu] Transformer un couple clé/valeur en hash imbriqués - Sephi-Chan - 02-08-2011

Je suis à la recherche d'un algorithme efficace pour réaliser une transformation d'un hash vers un autre. Comme un exemple vaut moult mots, je vais vous présenter la transformation que je souhaite effectuer.

Voici donc le hash de base. Il a pour particularité d'être trié par clé et par ordre alphabétique.


{
"npc.yoda.i_know_you" => "I know you...",
"npc.yoda.introduce" => "Hi! I'm Yoda!",
"npc.yoda.you_finished_the_quest" => "You achieved the quest!",
"quest.1.description" => "Bring me few endives and tomatoes, please.",
"quest.1.title" => "Endives and tomatoes",
"quest.2.description" => "Now, bring me few apples.",
"quest.2.title" => "Think different"
}


Mon but est de le transformer en ceci :


{
"npc" => {
"yoda" => {
"i_know_you" => "I know you...",
"introduce" => "Hi! I'm Yoda!",
"you_finished_the_quest" => "You achieved the quest!"
}
},
"quest" => {
"1" => {
"description" => "Bring me few endives and tomatoes, please.",
"title" => "Endives and tomatoes"
},
"2" => {
"description" => "Now, bring me few apples.",
"title" => "Think different"
}
}
}

Comme vous l'aurez compris, je veux que chaque point marque le début d'un nouveau hash. Bien sûr, l'imbrication doit être illimitée.

Voilà, voilà, si vous avez un algo à me conseiller, je suis preneur, peu importe le langage tant que c'est simple à porter. Smile

Merci d'avance ! Smile


RE: Transformer un couple clé/valeur en hash imbriqués - Hideaki - 02-08-2011

souhaites-tu un algo particulier, je veux dire existant ?
Créer un algo, pour faire ce que tu demandes, est assez simple, non ?


RE: Transformer un couple clé/valeur en hash imbriqués - Myrina - 02-08-2011

La récursivité semble de mise.
Voici une solution approchante du résultat; il y a un souci avec les clés purement numériques

<?php

$tab=array(
"npc.yoda.i_know_you" => "I know you...",
"npc.yoda.introduce" => "Hi! I\'m Yoda!",
"npc.yoda.you_finished_the_quest" => "You achieved the quest!",
"quest.n1.description" => "Bring me few endives and tomatoes, please.",
"quest.n1.title" => "Endives and tomatoes",
"quest.n2.description" => "Now, bring me few apples.",
"quest.n2.title" => "Think different"
);
$newTab=array();
foreach ($tab as $key => $val) {
$tmpTab=recursive(array(),$key,$val);
//chaque $tmpTab est correct unitairement mais la fonction suivante perturbe les clés numériques
$newTab=array_merge_recursive($newTab,$tmpTab);

}
echo "<pre>";print_r($newTab);

function recursive($tab,$key,$val) {
$multiKeys=explode('.',$key);
$firstKey=array_shift($multiKeys);
if (count($multiKeys)>0) {
// il reste des niveau de clés, donc on boucle
$newKey=implode('.',$multiKeys);
if (!isset($tab[$firstKey]) || (isset($tab[$firstKey]) && !is_array($tab[$firstKey]))) {
$tab[$firstKey]=array();
}
$ret=recursive($tab[$firstKey],$newKey,$val);
$tab[$firstKey]=array_merge($tab[$firstKey],$ret);
return $tab;
} else {
// fin de la récursivité, on fixe la valeur
$tab[$firstKey]=$val;
return $tab;
}

}

et le résultat obtenu:
Citation :Array
(
[npc] => Array
(
[yoda] => Array
(
[i_know_you] => I know you...
[introduce] => Hi! I\'m Yoda!
[you_finished_the_quest] => You achieved the quest!
)

)

[quest] => Array
(
[n1] => Array
(
[description] => Bring me few endives and tomatoes, please.
[title] => Endives and tomatoes
)

[n2] => Array
(
[description] => Now, bring me few apples.
[title] => Think different
)

)

)
Une transformation JSON en suivant ...



RE: Transformer un couple clé/valeur en hash imbriqués - niahoo - 02-08-2011

Voici ma proposition, bon en gros c'est la même chose qu'au dessus.

C'est améliorable, on peut gagner en élégance facilement je suppose mais ça fait le taf.

$flat = array(
"npc.yoda.i_know_you" => "I know you...",
"npc.yoda.introduce" => "Hi! I'm Yoda!",
"npc.yoda.you_finished_the_quest" => "You achieved the quest!",
"quest.1.description" => "Bring me few endives and tomatoes, please.",
"quest.1.title" => "Endives and tomatoes",
"quest.2.description" => "Now, bring me few apples.",
"quest.2.title" => "Think different"
);

function behead($string) {
$tokens = explode('.', $string);
$head = array_shift($tokens);
return array($head, implode('.', $tokens));
}

function nest_it($flat) {
$nested = array();
$recurse_on = array();
foreach ($flat as $k => $v) {
list($head, $tail) = behead($k);
if ('' == $tail)
$nested[$head] = $v;
else {
$nested[$head][$tail] = $v;
$recurse_on[$head] = true;
}
}
foreach ($recurse_on as $k => $_)
$nested[$k] = nest_it($nested[$k]);

return $nested;
}

print_r(nest_it($flat));

merci d'avoir mis un peu de challenge dans cette journée de mmmmm


RE: Transformer un couple clé/valeur en hash imbriqués - Sephi-Chan - 02-08-2011

Merci les gars ! Effectivement j'aurais pu le faire mais j'ai cédé à la facilité.
J'ai été bon à rien aujourd'hui, ou presque !

Je me contente donc de porter cette fonction. Elle va en fait me servir dans le cadre de l'affichage d'un module de traduction de chaîne. Je souhaite les organiser de manière hiérarchique afin que ce soit plus visuel pour l'utilisateur.


def behead(string)
tokens = string.split('.')
head = tokens.shift
tail = tokens.join('.')

[ head, tail ]
end


def nest(flat_hash)
nested = {}
recurse_on = {}

flat_hash.each do |key, value|
head, tail = behead(key)

if tail.empty?
nested[head] = value
else
nested[head] ||= {}
nested[head][tail] = value
recurse_on[head] = true
end
end

recurse_on.each do |key, value|
nested[key] = nest(nested[key])
end

nested
end

Merci bien ! Smile


RE: [Résolu] Transformer un couple clé/valeur en hash imbriqués - niahoo - 02-08-2011

'plaisir.

ox', scala pour voir comment ça fait ?

c'est sympa ces petits challenges, faudrait faire ça plus souvent dans plusieurs langages.