Avec l'entrée suivante:
[ { "points": 5, "rank": 1 }, { "points": 5, "rank": 1 }, { "points": 4, "rank": 3 }, { "points": 4, "rank": 3 }, { "points": 4, "rank": 3 }, { "points": 2, "rank": 6 }, { "points": 2, "rank": 6 }, { "points": 1, "rank": 8 } ]
Je souhaite générer la sortie suivante:
[5,5,4,4,4,2,2,1]
J'ai trouvé une solution (voir la réponse) mais je me demande s'il existe une meilleure façon de le faire.
4 Réponses :
Voici quelque chose qui fonctionne mais je crée une chaîne pour la diviser en éléments:
%dw 2.0 output application/json import * from dw::core::Strings var points =[5,5,4,4,4,2,2,1] var ranks = ((points reduce (i,acc=[]) -> acc + (if (acc[-1] == null ) [i,true] else [i,acc[-1][0]-i !=0])) reduce (i, acc=[[0,1]]) -> acc + ( if (i[1]==true) [(acc[-1][1]+acc[-1][0]),1 ] else [acc[-1][0] ,acc[-1][1]+1] ))[1 to -1] reduce (i,acc=[]) -> acc + i[0] --- (points zip ranks) map { points: $[0], rank: $[1] }
Sébastien, je pense avoir compris l'algorithme. Je ne sais pas si ma solution est plus simple mais elle se fait avec une seule reduce
. Essaie:
%dw 2.0 output application/dw var data = [5,5,4,4,4,2,2,1] --- (data reduce (e, acc = {idx: 0, result: []}) -> do { var i = acc.idx + 1 var last = if (isEmpty(acc.result)) {points: e, rank: 1} else acc.result[-1] --- { idx: i, result: acc.result + {points: e, rank: if (last.points == e) last.rank else i} } }).result
D'accord! C'est actuellement non programmé!
En supposant que mon algorithme est correct, sans utiliser de réduction,
[ { "points": 5, "rank": 1 }, { "points": 5, "rank": 1 }, { "points": 4, "rank": 3 }, { "points": 4, "rank": 3 }, { "points": 4, "rank": 3 }, { "points": 2, "rank": 6 }, { "points": 2, "rank": 6 }, { "points": 1, "rank": 8 } ]
Ce que fait la fonction est d'organiser le tableau d'entrée dans l'ordre décroissant et d'enregistrer l'index + 1 pour définir les positions de classement (rankArray). Ensuite, en utilisant l'index de la première occurrence de la valeur du tableau d'origine, obtenez l'index du rankArray et ce serait le rang. Cela se traduira par
%dw 2.0 output application/json import * from dw::core::Arrays var payload = [5,5,4,4,4,2,2,1] fun getRank(inputArray, value) = using (rankArray = payload orderBy $ map $$ + 1) rankArray[indexOf(inputArray, value)] --- payload map (value) -> { "points" : value, "rank": getRank(payload, value) }
vertigineux et correct
Je ne sais pas si cela couvre tous vos cas de test, mais voici une version plus courte du code que j'ai trouvée -
%dw 2.0 import * from dw::core::Arrays output application/json var inp=[5,5,4,4,4,2,2,1] --- inp map (v0,k0) -> { points:v0, rank:indexOf(inp,v0)+1 }
S'il vous plait, faite moi part de votre avis.
Bien fait, mettez maintenant un espace entre la map
et l'expression lambda pour que les autres ne soient pas confus;)
done.thanks @George :)
J'adore cette version !!! Bien joué.
Salut Sébastien, pourriez-vous s'il vous plaît expliquer l'algorithme en anglais sur la façon dont un rang est calculé?