DEV Community

Cover image for Ordinare la numerazione di un documento o lista espressa a livelli: 1.0, 1.1.2, 2.0,5.2.7
Paolo Carraro
Paolo Carraro

Posted on

Ordinare la numerazione di un documento o lista espressa a livelli: 1.0, 1.1.2, 2.0,5.2.7

Cosa ho imparato oggi? per ordinare delle stringhe che rappresentano la numerazione di un documento non possiamo ricorrere all'ordinamento alfanumerico.
Tipicamente un documento è ordinato usando un metodo per punti:
2.1.3

Quando vediamo questa numerazione traduciamo questi numeri cardinali in ordinali: di fatto leggiamo qualcosa come per esempio
terzo paragrafo del primo sottotitolo del secondo capitolo.
In più potremmo dover considerare che abbiamo casi del tipo
2.2
quindi mancanti della terza componente della numerazione in quanto questa si presuppone 0.

Normalizzare le parti che compongono la numerazione

La soluzione che ho trovato cercando risorse in internet è quella di normalizzare prima di tutto il numero di parti in modo che ne abbiamo sempre lo stesso numero da valutare.
Quindi passare da

1.3.5
2.1
5.3.5.6
10
Enter fullscreen mode Exit fullscreen mode

a

1.3.5.0
5.3.5.6
2.1.0.0
10.0.0.0
Enter fullscreen mode Exit fullscreen mode

Rendere ininfluente la posizione del numero aumentando il valore che lo esprime

Per evitare che 10 risulti minore di 2, come è per l'ordinamento alfanumerico, il trucco è quello di aumentare le cifre che compongono la numerazione sommando un numero più alto della cifra che ci aspettiamo essere il massimo. Per esempio sommando sempre 100 ad ogni parte otteniamo:

101.103.105.100
105.103.105.106
102.101.100.100
110.100.100.100
Enter fullscreen mode Exit fullscreen mode

Quello che abbiamo, nonostante siano espressi da numeri, lo andremo a valutare come stringa in quanto semplifica di molto la comparazione e inoltre permette anche di gestire numerazioni contenenti lettere. Per esempio potremmo avere

7.1.b
7.2
Enter fullscreen mode Exit fullscreen mode

che diventa

107.101.10b.100
107.102.100.100
Enter fullscreen mode Exit fullscreen mode

Il codice per implementare questo algoritmo l'ho scritto così

// considerando che si possa arrivare ad una numerazione di centinaia
const templatePart = '1000';
// numerazione composta da 6 livelli di annidamento
const template = [templatePart, templatePart, templatePart, templatePart, templatePart, templatePart];
const convertForComparing = (parNumeration: string) => {
  // "somma" del numero template
  let parts = parNumeration.split('.').map(
    (p) => templatePart.substring(0, templatePart.length - p.length) + p);
  // normalizzazione del numero di parti
  parts = [...parts, ...template.slice(parts.length)];
  return parts.join('.');
};

const sortByParagraphNumeration = (a: Item, b: Item) => {
  const pa = convertForComparing(a.par.toLowerCase() || '');
  const pb = convertForComparing(b.par.toLowerCase() || '');

  if (pa < pb) {
    return -1;
  }
  if (pa > pb) {
    return 1;
  }
  return 0;
};
Enter fullscreen mode Exit fullscreen mode

La spiegazione di sicuro è manchevole di formalismo e fin troppo empirica ma nel mio caso pare funzionare a dovere.
E voi come avreste risolto?

Latest comments (0)