Как сделать обратную сортировку пунктов?

Имеется большое количество пунктов по такой структуре:

  • Ноутбуки
    -- Acer
    -- Samsung
    -- Lenovo

  • Планшеты
    -- Acer
    -- Samsung
    -- Lenovo

  • Телевизоры
    -- Acer
    -- Samsung
    -- Lenovo

Как можно в модуле вывода категорий вывести с помощью JS категории так, чтобы вид был подобный:

  • Samsung:
    -- Телевизоры
    -- Ноутбуки
    -- Планшеты
  • Acer
    --Телевизоры
    --Ноутбуки
    --Планшеты
  • Lenovo
    -- Телевизоры
    -- Ноутбуки
    --Планшеты

<ul>
  <li class="heading"><a>Ноутбуки</a></li>
  <li>      
     <ul>
       <li><a>Acer</a></li>
       <li><a>Samsung</a></li>
       <li><a>Lenovo</a></li>
     </ul>
  </li>
</ul>

<ul>
  <li class="heading"><a>Ноутбуки</a></li>
  <li>      
     <ul>
       <li><a>Acer</a></li>
       <li><a>Samsung</a></li>
       <li><a>Lenovo</a></li>
     </ul>
   </li>
</ul>

<ul>
  <li class="heading"><a>Планшеты</a></li>
  <li>      
     <ul>
       <li><a>Acer</a></li>
       <li><a>Samsung</a></li>
       <li><a>Lenovo</a></li>
     </ul>
  </li>
</ul>


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

Автор решения: wololo

Как вариант, пройтись по исходному списку, сформировав из него Map. В качестве ключа использовать название компании, а в качестве значения массив разновидностей техники, производимой компанией.

Затем пройтись по Map, формируя результирующий список. Ключи Map (названия компаний) использовать в качестве элементов списка, а из значений Map (массивов разновидностей техники) формировать вложенные списки.

let heading = document.querySelectorAll(".heading");
let map = new Map();
for (let i = 0; i < heading.length; ++i) {
    let a = heading[i].querySelectorAll("a");
    let groupName = a[0].textContent.trim();
    for (let j = 1; j < a.length; ++j) {
        let companyName = a[j].textContent.trim();
        let companyGroups = map.get(companyName);
        if (companyGroups)
            companyGroups.push(groupName);
        else
            map.set(companyName, [groupName]);
    }
}

let compare = (new Intl.Collator("ru")).compare;
let ul = document.createElement("ul");
ul.className = "some-style";
let companies = Array.from(map.keys()).sort(compare);
for (let companyName of companies) {
    let li = document.createElement("li");
    let a = document.createElement("a");
    a.textContent = companyName;
    li.append(a);
    
    let li_ul = document.createElement("ul");
    let companyGroups = map.get(companyName).sort(compare);
    for (let groupName of companyGroups) {
        let li = document.createElement("li");
        let a = document.createElement("a");
        a.textContent = groupName;
        li.append(a);
        li_ul.append(li);
    }
    li.append(li_ul);
    
    ul.append(li);
}

document.body.append(ul);
.some-style {
    background-color: silver;
    border: 1px solid black;
}
<ul>
  <li class="heading"><a>Телевизоры</a>   
     <ul>
       <li><a>Samsung</a></li>
       <li><a>Lenovo</a></li>
     </ul>
  </li>
  <li class="heading"><a>Планшеты</a>   
     <ul>
       <li><a>Lenovo</a></li>
       <li><a>Samsung</a></li>
       <li><a>Acer</a></li>
     </ul>
   </li>
  <li class="heading"><a>Ноутбуки</a>     
     <ul>
       <li><a>Lenovo</a></li>
       <li><a>Samsung</a></li>
       <li><a>Acer</a></li>
     </ul>
  </li>
</ul>

→ Ссылка