Javascript сортировка массива по "группам" и поддержание порядка - PullRequest
1 голос
/ 31 марта 2020

У меня есть набор данных, который выглядит следующим образом:

[
{
    "name": "Item1",
    "section": "section1",
    "total": 3,
}, {
    "name": "Item1",
    "section": "section2",
    "total": 4,
}{
    "name": "Item1",
    "section": "section3",
    "total": 7,
}, {
    "name": "Item2",
    "section": "section1",
    "total": 1,
}, {
    "name": "Item2",
    "section": "section2",
    "total": 2,
}, {
    "name": "Item2",
    "section": "section3",
    "total": 3,
    }
]

Мне нужно отсортировать массив только по общему значению в элементе раздела 3, но сохранить порядок (section1, section2, затем section 3 ) по имени. Таким образом, для этого примера Item2 должен переместить все 3 его строки выше Item1. Я пробовал сортировать по нескольким элементам, но это не поддерживает порядок, который мне нужен. Должен ли я просто получить самый маленький / самый большой, взять связанные элементы и поместить их в новый массив и повторить или есть более логичный способ выполнить sh это?

Я также использую angular и начинаю сетку, если есть что-то, что я могу использовать там.

Ответы [ 5 ]

1 голос
/ 31 марта 2020

Вы можете

  • собрать все объекты одной группы и получить итоговую сумму для сортировки,
  • отсортировать по группам total значение,
  • получить плоский массив всех объектов.

const
    data = [{ name: "Item1", section: "section1", total: 3 }, { name: "Item1", section: "section2", total: 4 }, { name: "Item1", section: "section3", total: 7 }, { name: "Item2", section: "section1", total: 1 }, { name: "Item2", section: "section2", total: 2 }, { name: "Item2", section: "section3", total: 3 }],
    result = Object
        .values(data.reduce((r, o) => {
            r[o.name] = r[o.name] || { payload: [] };
            r[o.name].payload.push(o);
            if (o.section === 'section3') r[o.name].total = o.total;
            return r;
        }, {}))
        .sort(({ total: a }, { total: b }) => a - b)
        .flatMap(({ payload }) => payload);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 31 марта 2020

Я бы создал карту, используя name в качестве ключа и total в качестве значения для элементов, где section равно section3. Затем вы можете выполнить сортировку с использованием карты.

Это позволит отсортировать все элементы по значению total в section3 и сохранить исходный порядок сортировки, где значение сортировки совпадает.

const map = new Map<string, number>(this.data
  .filter(x => x.section === 'section3')
  .map(x => [ x.name, x.total ]));

this.sorted = this.data.slice()
  .sort((a, b) => map.get(a.name) - map.get(b.name));

Это зависит от того, как структурированы и упорядочены данные, как указано в вашем вопросе.

DEMO: https://stackblitz.com/edit/angular-fsswdq

0 голосов
/ 31 марта 2020

Приоритетная сортировка

const data = [{"name":"Item1","section":"section1","total":3},{"name":"Item1","section":"section2","total":4},{"name":"Item1","section":"section3","total":7},{"name":"Item2","section":"section1","total":1},{"name":"Item2","section":"section2","total":2},{"name":"Item2","section":"section3","total":3}];
console.log(
  data.sort((a, b) => {
    const diff = a.total - b.total;
    if (diff) return diff;
    return b.section.localeCompare(a.section);
  })
);
.as-console-row {color: blue!important}
0 голосов
/ 31 марта 2020

Сначала необходимо «сгруппировать» набор данных по name, а затем выполнить сортировку по total.

let items = [{
  "name": "Item1",
  "section": "section1",
  "total": 3,
}, {
  "name": "Item1",
  "section": "section2",
  "total": 4,
}, {
  "name": "Item1",
  "section": "section3",
  "total": 7,
}, {
  "name": "Item2",
  "section": "section1",
  "total": 1,
}, {
  "name": "Item2",
  "section": "section2",
  "total": 2,
}, {
  "name": "Item2",
  "section": "section3",
  "total": 3,
}];

let groups = {};

for (let item of items) {
  if (!groups[item.name]) {
    groups[item.name] = {
      data: []
    };
  }

  // Grouping by `name`
  groups[item.name].data.push(item);

  // Store the `total`
  if (item.section == "section3") {
    groups[item.name].key = item.total;
  }
}

// sort the groups, this will maintain the order of sections (1,2 and 3) in each group
let sortedGroups = Object.values(groups).sort((a, b) => {
  return a.key - b.key; // ascending
});

// then flatten the groups
let flatten = [].concat(...sortedGroups.map(x => x.data));

console.log(flatten);
0 голосов
/ 31 марта 2020

var array = [
{
    "name": "Item1",
    "section": "section1",
    "total": 3,
}, {
    "name": "Item1",
    "section": "section2",
    "total": 4,
},{
    "name": "Item1",
    "section": "section3",
    "total": 7,
}, {
    "name": "Item2",
    "section": "section1",
    "total": 1,
}, {
    "name": "Item2",
    "section": "section2",
    "total": 2,
}, {
    "name": "Item2",
    "section": "section3",
    "total": 3,
    }
];

array = array.sort((o1, o2)=>{

if(o1.section === o2.section && o1.section === 'section3') {
   return o1.total - o2.total;
} else {
  return o1.section === 'section3' ? 1 : -1;
}
});

console.log(array);

Вот вывод

[
  {
    "name": "Item1",
    "section": "section1",
    "total": 3
  },
  {
    "name": "Item1",
    "section": "section2",
    "total": 4
  },
  {
    "name": "Item2",
    "section": "section1",
    "total": 1
  },
  {
    "name": "Item2",
    "section": "section2",
    "total": 2
  },
  {
    "name": "Item2",
    "section": "section3",
    "total": 3
  },
  {
    "name": "Item1",
    "section": "section3",
    "total": 7
  }
]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...