[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.
Merci d'avance !
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 !
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.
|