LINUX.ORG.RU

Сортировка массива по двум параметрам

 ,


0

1

Имеется массив хешей:

my @meters = (
    {seq=>3, name=>"Їдальня"}, 
    {seq=>5, name=>"Контора"},
    {seq=>6, name=>"Госпдвір"}, 
    {seq=>4, name=>"Склад"}, 
    {seq=>2, name=>"Госпдвір"}, 
);
Нужно отсортировать по seq, но одинаковые name должны быть рядом. Должно выйти так:
{seq=>2, name=>"Госпдвір"},
{seq=>6, name=>"Госпдвір"}, 
{seq=>3, name=>"Їдальня"}, 
{seq=>4, name=>"Склад"},
{seq=>5, name=>"Контора"},
Ничего короткого и ясного не получается, одни монстры :) . И да, выборка этого массива производится с БД. Может в sql есть решения?

«order by name, seq» не устроит ? Или нужно чтоб первым был обязательно минимальный seq ?

zaz ★★★★
()
Ответ на: комментарий от SyntaxError

У меня получилось чтото в таком духе - не знаю насколько оно правильно работает и лутчше/хуже того что есть у вас. Но возможно будет полезно ...

#!/usr/bin/perl

use Data::Dumper;

my @meters = (
    {seq=>3, name=>"Їдальня"},
    {seq=>5, name=>"Контора"},
    {seq=>6, name=>"Госпдвір"},
    {seq=>4, name=>"Склад"},
    {seq=>2, name=>"Госпдвір"},
);

sub metOrder {
        my $items  = shift;
        my %minSeq;

        foreach $i (@$items) {
                if((! $minseq{$i->{name}}) or ($minseq{$i->{name}} > $i->{seq})) {
                        $minSeq{$i->{name}} = $i->{seq}
                };
        }

        return sort {
                ($minSeq{$a->{name}} != $minSeq{$b->{name}})
                        ?($minSeq{$a->{name}} <=> $minSeq{$b->{name}})
                        :($a->{seq} <=> $b->{seq})
        } @$items;
}

my @sorted = metOrder( \@meters );

print Dumper( \@sorted );

zaz ★★★★
()
Последнее исправление: zaz (всего исправлений: 1)
Ответ на: комментарий от anonymous

Что из этих груп должно быть первым и почему?


Массив уже отсортирован по дате, это поле я не указал. Группируется по первому вхождению name, то есть seq первого попавшегося name берется за основу. Внутри группы сортировка не имеет значения.

SyntaxError
() автор топика
Ответ на: комментарий от zaz

не знаю насколько оно правильно работает и лутчше/хуже того что есть у вас.

У меня строк на 20 и два цикла. У вас лаконично и просто. Еще раз спасибо.

P.S. Мелкие ошибки в строках 17-18

17,18c17,18
<         foreach $i (@$items) {
<                 if((! $minseq{$i->{name}}) or ($minseq{$i->{name}} > $i->{seq})) {
---
>         foreach my $i (@$items) {
>                 if((! $minSeq{$i->{name}}) or ($minSeq{$i->{name}} > $i->{seq})) {

SyntaxError
() автор топика
Ответ на: комментарий от SyntaxError

незачто, да я это тоже заметил у себя после сабмита поста. Я если честно не особо в перле, так иногда сопутсвующие скрипты пишу ...

zaz ★★★★
()
Ответ на: комментарий от SyntaxError

Вообще-то благодаря zaz вопрос решен. Тему можно закрывать.

SyntaxError
() автор топика

В перле ФВП есть? Можно со скалы перевести, вот навскидку

Map(5 -> "c", 1 -> "a", 6 -> "b", 8 -> "a", 2 -> "b", 7 -> "d", 3 -> "b", 4 -> "a")
  .groupBy(_._2)
  .values
  .toList
  .sortBy(_.keys.min)
  .map(x => SortedMap(x.toSeq: _*))
  .flatten
// res55: List[(Int, String)] = List((1,a), (4,a), (8,a), (2,b), (3,b), (6,b), (5,c), (7,d))

Я ответ не читал, сложность сравнивать не берусь, но у меня, по-моему, зашкаливает)

anonymous
()
Ответ на: комментарий от anonymous

Я это вообще к тому, что вон у меня groupBy есть, можно его на sql переложить, например, тогда первых 3 вызова (groupBy, values & toList) уходят, (а мб и сортировка, но тогда запрос будет монструозный), тебе вообще фигня остается.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.