JS как сгруппировать список по по первому символу (числа, английский, каждая русская буква отдельно)

на сайте имеется вот такой список

<ul id="tags" class="tags">
     <li><a href="#">Аб</a></li>
     <li><a href="#">Аывдаорыдва</a></li>
     <li><a href="#">JavaScript</a></li>
     <li><a href="#">24234</a></li>
     <li><a href="#">Python</a></li>
     <li><a href="#">Олфвфпалвыфа</a></li>
     <li><a href="#">Жлпалвфыа</a></li>
     <li><a href="#">99734234234</a></li>
     <li><a href="#">Аопфывалвгфы</a></li>
     <li><a href="#">Бывфлрлпалыфв</a></li>
</ul>

В конечном итоге должно получится вот так

            <ul id="tags" class="tags">
                <ol class="tags__0-9" data-letter="0-9">
                    <span>0-9</span>
                    <li><a href="#">24234</a></li>
                    <li><a href="#">99734234234</a></li>
                </ol>
                <ol class="tags__A-Z" data-letter="A-Z">
                    <span>A-Z</span>
                    <li><a href="#">JavaScript</a></li>
                    <li><a href="#">Python</a></li>
                </ol>
                <ol class="tags__a1" data-letter="А">
                    <span>А</span>
                    <li><a href="#">Аб</a></li>
                    <li><a href="#">Аопфывалвгфы</a></li>
                    <li><a href="#">Аывдаорыдва</a></li>
                </ol>
                <ol class="tags__B1" data-letter="Б">
                    <span>Б</span>
                    <li><a href="#">Бывфлрлпалыфв</a></li>
                </ol>
                <ol class="tags__ZH1" data-letter="Ж">
                    <span>Ж</span>
                    <li><a href="#">Жлпалвфыа</a></li>
                </ol>
                <ol class="tags__O1" data-letter="О">
                    <span>О</span>
                    <li><a href="#">Олфвфпалвыфа</a></li>
                </ol>
            </ul>

Частично смог сделать каждое число букву отдельно смог сгрупировать, но нужно чтобы числа и английский шли в одном ol а не каждая буква и число отдельно

$(document).ready(function () {
   sortList();

   $('.tags > li').each(function () {
       var letter = $('a', this).text().charAt(0);

       if (!$(this).parent().find('[data-letter="'+ letter +'"]').length) {
           $(this).parent().append('<ol class="tags__' + transliterate(letter) + '" data-letter="'+ letter+'"><span>'+ letter +'</span></ol>');
       }
       $(this).parent().find('[data-letter="'+ letter +'"]').append(this);
   });
});

На большего поиск по просторам интернета не дал ничего к сожалению Спасибо если кто поможет


Ответы (1 шт):

Автор решения: OPTIMUS PRIME

Для каждого <li>: Взять существующий или создать новый <ol>, пихнуть li туда. Список существующих ol хранится в дополнительном объекте, с ключами "0-9", "A-Z", "А", "Б", "В", "Г"... :

const translit = (function() {
  let dict = { // Словарь для перевода русских букв.
    "а": "A",
    "б": "B",
    "ж": "ZH",
    "о": "O",
  };
  
  return function(ru_letter) {
    return dict[ ru_letter.toLowerCase() ];
  }
})();

/***/
let ol_storage = {}; // Хранилище для всех <ol>, ключ: <ol data-letter="ключ"

let ul = document.querySelector("#tags");
let li = [...document.querySelectorAll("#tags li")];
// [...элементы] — отправляет их в массив, у которого есть встроенный метод sort.

li.sort((a, b) => a.textContent < b.textContent ? -1 : 1);
// Сразу сортирую все li, чтобы лежали в нужном порядке.

for (let i = 0; i < li.length; i++) {
  let char_0 = li[i].children[0].textContent.charAt(0);
  
  switch (true) {
    case /[0-9]/i.test(char_0) : insert_numeric(li[i], char_0); break;
    case /[a-z]/i.test(char_0) : insert_english(li[i], char_0); break;
    case /[а-яё]/i.test(char_0): insert_russian(li[i], char_0); break;
  }
}

/***/
function create_ol(tags, letter) {
  // tags, letter - сохранены исходные названия. Может надо подумать над другими.
  let ol = document.createElement("ol");

  ol.className = "tags__" + tags;
  ol.dataset.letter = letter;  
  ol.innerHTML = "<span>" + letter + "</span>";
  
  ol_storage[letter] = ol; // Созданный ol добавляется в хранилище
  ul.appendChild(ol); // и одновременно на страницу.
  
  return ol;
}

function insert_numeric(li, char_0) {
  (ol_storage["0-9"] || create_ol("0-9", "0-9")).appendChild(li);
  // Если уже существует <ol> для ключа "0-9" — берется он,
  // если нет - вызывается create_ol, создает новый.
}

function insert_english(li, char_0) {
  (ol_storage["A-Z"] || create_ol("A-Z", "A-Z")).appendChild(li);
}

function insert_russian(li, char_0) {
  let lower = char_0.toLowerCase(), upper = char_0.toUpperCase();
  
  let ol = ol_storage[upper] || create_ol(translit(lower) + "1", upper);
  ol.appendChild(li);
}
<ul id="tags" class="tags">
  <li><a href="#">Аб</a></li>
  <li><a href="#">Аывдаорыдва</a></li>
  <li><a href="#">JavaScript</a></li>
  <li><a href="#">24234</a></li>
  <li><a href="#">Python</a></li>
  <li><a href="#">Олфвфпалвыфа</a></li>
  <li><a href="#">Жлпалвфыа</a></li>
  <li><a href="#">99734234234</a></li>
  <li><a href="#">Аопфывалвгфы</a></li>
  <li><a href="#">Бывфлрлпалыфв</a></li>
</ul>

→ Ссылка