Fonctions de tableaux
Les fonctions de tableaux vous permettent de manipuler des listes de données : calculer des sommes, filtrer des éléments, transformer des valeurs, et plus encore.
Agrégation
Ces fonctions réduisent un tableau à une seule valeur.
tableau.sum()
Calcule la somme de tous les éléments d'un tableau numérique.
[10, 20, 30].sum() // 60
[1.5, 2.5, 3].sum() // 7
commande.produits.prixHT.sum() // Somme des prix HTBon à savoir : [].sum()sur un tableau vide retourne 0. Les éléments null sont ignorés. Des montants de devises différentes sont convertis avant l'addition quand votre organisation fige ses taux de change : voir Montants en devises.
tableau.average()
Calcule la moyenne arithmétique des éléments d'un tableau.
[10, 20, 30].average() // 20
[100, 80, 90, 70].average() // 85
commande.produits.notes.average() // Note moyennemax(tableau) ou max(a, b, c...)
Retourne la valeur maximale. Fonctionne avec un tableau ou plusieurs arguments.
max([5, 2, 8, 1]) // 8
max(10, 20, 5) // 20
max(commande.produits.stock) // Stock le plus élevéBon à savoir : max([])sur un tableau vide retourne 0.
valeur.count()
Retourne le nombre d'éléments dans un tableau ou de caractères dans une chaîne.
[1, 2, 3, 4, 5].count() // 5
"Bonjour".count() // 7
commande.produits.count() // Nombre de produitsMontants en devises
Quand votre organisation fige un taux de change sur ses documents (une propriété « taux de change » déclarée sur la commande, la facture…), sum(), average(), max(), sort() et best() ne mélangent plus des montants de devises différentes : chaque montant est converti dans la devise finale avec le taux figé de son propre document, puis arrondi aux décimales de cette devise (au centime pour l'euro), avant d'être additionné ou comparé. Sans taux déclaré, ces fonctions additionnent les nombres tels quels, comme avant.
La devise finale
C'est la devise du champ qui reçoit le résultat (sa devise fixe, ou celle de sa propriété devise), ou celle du widget ou de la colonne. Si rien ne la déclare et que tous les montants sont dans une même devise, le résultat reste dans cette devise, sans conversion. S'il y en a au moins deux, c'est la devise de votre société.
// Taux figé de la commande USD : 0,85 (1 USD = 0,85 EUR), devise société EUR
findObjects(order, {}).amountHT.sum()
// 1 000 USD + 1 000 EUR → 850,00 + 1 000,00 = 1 850,00 EUR
// Toutes les commandes en CHF, champ sans devise → total en CHF, inchangé
// Même liste vers un champ en EUR → convertie en EUR
// Trois montants de 1,03 USD à 0,85 → 3 × 0,88 = 2,64 EUR (chaque montant arrondi)Ce qui garde la devise d'un montant
Un montant garde sa devise quand on le multiplie ou le divise par un nombre, qu'on l'arrondit (toFixed), qu'on change son signe (negate, negateIf), qu'on lui ajoute ou retranche un nombre, ou qu'on l'ajoute à un montant de même devise. Filtrer, trier, mettre en variable ne change rien. Le rapport de deux montants de même devise (amountHT / amountTTC) est un simple nombre, sans devise. Additionner deux devises différentes, ou diviser l'une par l'autre, perd en revanche la devise : le résultat est compté tel quel et signalé, même multiplié ensuite par un montant.
findObjects(order, {}).map(o => o.amountHT * 2).sum() // toujours converti
max(0, expenseClaim.sumAmountTTC - expenseClaim.advanceAmount) // garde la devise du montant
findObjects(order, {}).map(o => o.amountHT / o.amountTTC) // nombres sans devise
findObjects(order, {}).map(o => o.amountHT / o.fraisEUR) // USD ÷ EUR : devise perdue, signalé
findObjects(order, {}).map(o => o.amountHT + o.fraisUSD).sum() // devise perdue : compté tel quel, signalé
lignes.map(l => l.prix * l.quantite).sum() // nombres sans devise : additionnés tels quelsmax, sort et best
Ils comparent les montants dans la devise finale. max() rend le plus grand montant converti ; sort() et best() rendent les éléments d'origine, dans l'ordre des montants convertis.
// 1 000 USD (850 EUR au taux figé) et 900 EUR
max(findObjects(order, {}).amountHT) // 900 : la commande en euros est la plus grosseAttention : une conversion ne produit jamais d'erreur. Un montant qu'on ne sait pas convertir (document sans taux figé, taux vers une autre devise, devise perdue par un calcul, valeur en erreur) est compté tel quel, et le résultat est signalé par un point ambre. Un taux provisoire (document daté dans le futur) est signalé de la même façon. Des lignes sans devise de plusieurs documents ne sont jamais converties : additionnez plutôt les totaux des documents, qui ont leur taux.
Filtrage et recherche
Ces fonctions permettent de sélectionner des éléments selon des critères.
tableau.filter(condition)
Retourne un nouveau tableau contenant uniquement les éléments qui satisfont la condition. Le paramètre de la lambda nomme l'élément courant : l => l.champ.
// Filtrer les nombres supérieurs à 10
[5, 15, 8, 20, 3].filter(x => x > 10) // [15, 20]
// Filtrer les produits en stock
commande.produits.filter(x => x.stock > 0)
// Filtrer les commandes validées
client.commandes.filter(x => x.statut === "validée")
// Condition multiple
commande.produits.filter(x => x.prix > 50 && x.stock > 0)Astuce : le paramètre que vous écrivez avant la flèche nomme l'élément courant, et vous choisissez ce nom : ligne => ligne.montant se lit mieux que x => x.montant. Il n'existe que dans le corps de sa lambda.
tableau.find(condition)
Retourne le premier élément qui satisfait la condition, ou false si aucun n'est trouvé.
// Trouver le premier nombre pair
[1, 3, 4, 7, 8].find(x => x % 2 === 0) // 4
// Trouver le premier produit en rupture
commande.produits.find(x => x.stock === 0)
// Trouver une commande spécifique
client.commandes.find(x => x.numero === "CMD-001")Attention : Cette fonction retourne false si aucun élément n'est trouvé, pas un tableau vide. Pensez à gérer ce cas avec une condition.
tableau.best(clé) ou tableau.best(clé, "asc")
Retourne l'élément qui possède la valeur maximale d'une clé donnée. Passez "asc" en second argument pour obtenir le minimum à la place. Le paramètre de la lambda nomme l'élément courant : l => l.champ.
// Le plus grand nombre
[3, 1, 5, 2].best(x => x) // 5
// Le plus petit nombre
[3, 1, 5, 2].best(x => x, "asc") // 1
// Le projet le plus rentable
findObjects(project, {}).best(x => x.realGrossProfit)
// Le nom du produit le moins cher
commande.produits.best(x => x.prix, "asc").nomBon à savoir : best retourne l'élément complet, pas la valeur de la clé. Sur un tableau vide, elle retourne null. Les éléments dont la clé est null sont ignorés. Une clé monétaire se compare dans la devise finale (voir Montants en devises).
tableau.unique()
Élimine les doublons et retourne un tableau avec des valeurs uniques.
[1, 1, 2, 3, 3, 3, 4].unique() // [1, 2, 3, 4]
["a", "b", "a", "c"].unique() // ["a", "b", "c"]
commande.produits.tva.unique() // Taux de TVA uniquesTransformation
Ces fonctions créent de nouveaux tableaux en transformant chaque élément.
tableau.map(expression)
Applique une transformation à chaque élément et retourne un nouveau tableau. Le paramètre de la lambda nomme l'élément courant : l => l.champ.
// Doubler chaque nombre
[1, 2, 3].map(x => x * 2) // [2, 4, 6]
// Extraire un champ de chaque objet
commande.produits.map(x => x.nom) // ["Produit A", "Produit B", ...]
// Calculer le TTC de chaque produit
commande.produits.map(x => x.prixHT * 1.20)
// Formater chaque valeur
[10, 20, 30].map(x => x.concat(" €")) // ["10 €", "20 €", "30 €"]tableau.flatten()
Retire un niveau d'imbrication : un tableau de tableaux devient un tableau simple. Utile quand vous lisez, à travers une liste, un champ qui contient lui-même plusieurs valeurs (étiquettes, choix multiples) : vous obtenez alors une liste de valeurs par élément.
// Les étiquettes du projet de chaque ligne : une liste par ligne
ndf.lignes.projet.tags // [["Frais généraux"], ["Client", "Urgent"]]
// Une seule liste, à plat
ndf.lignes.projet.tags.flatten() // ["Frais généraux", "Client", "Urgent"]
// Au moins un projet des lignes porte-t-il l'étiquette ?
ndf.lignes.projet.tags.flatten().includes("Urgent")
// Toutes les étiquettes des produits, sans doublon
commande.produits.tags.flatten().unique()Bon à savoir : sans traversée de liste, flatten est inutile. commande.projet.tags.includes("Urgent") suffit, car une commande n'a qu'un projet. Un tableau déjà plat est rendu tel quel.
tableau.sort() ou tableau.sort(clé)
Trie un tableau en ordre croissant. Sans clé, trie directement les éléments (nombres, dates ou texte). Avec une clé, trie selon la valeur renvoyée par l'expression pour chaque élément. Le paramètre de la lambda nomme l'élément courant : l => l.champ.
// Trier des nombres
[5, 2, 8, 1, 9].sort() // [1, 2, 5, 8, 9]
// Trier du texte par ordre alphabétique
["banane", "abricot", "cerise"].sort() // ["abricot", "banane", "cerise"]
// Trier des objets par un champ
commande.produits.sort(x => x.prix) // Produits triés par prix croissant
client.commandes.sort(x => x.date) // Commandes triées par date
client.factures.sort(x => x.date) // Factures triées par dateBon à savoir : une clé monétaire se compare dans la devise finale ; les éléments rendus sont ceux d'origine, seul leur ordre en dépend (voir Montants en devises).
Manipulation
Ces fonctions permettent de combiner, découper ou assembler des tableaux.
arg1.concat(arg2, ...)
Concatène des chaînes, nombres ou tableaux. Très polyvalent !
// Concaténer des chaînes
"Bonjour ".concat("Constance") // "Bonjour Constance"
// Mélanger texte et nombres
"Total : ".concat(150, " €") // "Total : 150 €"
// Concaténer des tableaux
[1, 2].concat([3, 4]) // [1, 2, 3, 4]tableau.join(séparateur)
Joint les éléments d'un tableau en une chaîne avec un séparateur.
["a", "b", "c"].join(", ") // "a, b, c"
["Paris", "Lyon", "Marseille"].join(" - ") // "Paris - Lyon - Marseille"
produit.categories.join(", ") // "Catégorie1, Catégorie2"
["Paris", "Lyon"].join("\n") // "Paris" et "Lyon", une ville par lignetexteOuTableau.slice(début, fin?)
Extrait une portion d'une chaîne ou d'un tableau, entre deux bornes. La position de début commence à 0, la fin est exclue, et une fin absente va jusqu'au bout. Un indice négatif compte depuis la fin.
// Les 3 premiers caractères : de 0 à 3 (exclu)
"Bonjour".slice(0, 3) // "Bon"
// De la position 3 à la position 7 (exclue)
"Bonjour".slice(3, 7) // "jour"
// Sans fin : jusqu'au bout
"Bonjour".slice(3) // "jour"
// Négatif : les 4 derniers caractères
"Bonjour".slice(-4) // "jour"
// Les 2 premiers éléments d'un tableau
[1, 2, 3, 4, 5].slice(0, 2) // [1, 2]
// Limiter la longueur d'un nom
client.nom.slice(0, 20)slice remplace l'ancienne fonction cut(source, longueur, depuis?), qui prenait une longueur puis un décalage. La traduction est cut(s, n, d) → s.slice(d, d + n). Et un indice négatif, que cut ramenait à 0, compte désormais depuis la fin : texte.slice(texte.indexOf("x")) rend le dernier caractère quand « x » est absent, puisque indexOf rend -1. La forme sûre reste indexOf(…) + 1.tableau1.zip(tableau2)
Entrelace deux tableaux en alternant leurs éléments.
[1, 3, 5].zip([2, 4, 6]) // [1, 2, 3, 4, 5, 6]
["a", "c"].zip(["b", "d"]) // ["a", "b", "c", "d"]Exemples combinés
En pratique, vous combinerez souvent plusieurs fonctions. Voici des exemples réalistes.
Calculer le total d'une commande
let lignes = commande.produits;
let sousTotal = lignes.map(ligne => ligne.quantite * ligne.prixUnitaire);
sousTotal.sum()Trouver les produits à réapprovisionner
let produits = magasin.produits;
let enRupture = commande.produits.filter(produit => produit.stock < produit.stockMinimum);
let noms = enRupture.map(x => x.nom);
noms.join(", ")Résultat : "Produit A, Produit C, Produit F"
Calculer la TVA par taux
let produits = commande.produits;
let tauxUniques = commande.produits.map(produit => produit.tva).unique();
tauxUniques.map(tauxUnique => "TVA ".concat(tauxUnique, "% : ",
commande.produits.filter(produit => produit.tva === tauxUnique).map(produit => produit.prixHT * produit.tva / 100
).sum(),
" €"
)
)Résultat : ["TVA 5.5% : 12.50 €", "TVA 20% : 45.00 €"]
Prochaine étape
Découvrez maintenant les fonctions de manipulation de dates pour travailler avec des échéances, des périodes et des calendriers.