List 用Perl在O(n)中自定义列表的重新排序/排序

List 用Perl在O(n)中自定义列表的重新排序/排序,list,perl,sorting,reference,List,Perl,Sorting,Reference,我正在重新订购一份清单 我的原始列表,输入:@lineItems [ {id=> 'id1', ..}, {id=> 'id2', 'groupId'=>45D,.. }, {id=> 'id3', 'groupId'=>56A, .. }, {id=> 'id4', 'groupId'=>45D, 'isParent'=>1 .. }, {id=> 'id5', ..}, {id=> 'id6', 'group

我正在重新订购一份清单

我的原始列表,输入:@lineItems

[
  {id=> 'id1', ..},
  {id=> 'id2', 'groupId'=>45D,.. },
  {id=> 'id3', 'groupId'=>56A, .. },
  {id=> 'id4', 'groupId'=>45D, 'isParent'=>1 .. },
  {id=> 'id5', ..},
  {id=> 'id6', 'groupId'=>56A, 'isParent'=>1.. },
]
在上面的列表中,groupId表示该项是bundle的一部分。GroupId唯一地确定捆绑组。如果组Id不存在,则其为非捆绑项

目标-对列表重新排序,以便在每个捆绑包的开始处,所有捆绑包项目都应与父项目一起分组,并且捆绑包和非捆绑包项目的传入顺序(当groupId不存在时)应保持不变。 按O(n)对列表进行排序

预期产出:

    [
     {id=> 'id1', ..},
     {id=> 'id4', 'groupId'=>45D, 'isParent'=>1 .. },
     {id=> 'id2', 'groupId'=>45D,.. },
     {id=> 'id6', 'groupId'=>56A, 'isParent'=>1.. },
     {id=> 'id3', 'groupId'=>56A, .. },
     {id=> 'id5', ..},
    ]
这是我的算法:

  • 创建ID的sortedList=@sortedLineitemsIds
  • 使用sortedIdsList形成最终排序列表
  • 1的代码

            my $grouIdToLineItemIdMap;
    
            foreach my $lineItem (@$lineItems) {
                if(!$lineItem->{'groupID'}) { #non bundle item, add as it is
                    push @sortedLineitemsIds, $lineItem->{'id'};
                } else {
                    if($lineItem->{'IsParent'} eq 1) {
                        unshift @{$grouIdToLineItemIdMap->{$groupId}}, $lineItem->{'id'};
                    } else {
                        push @{$grouIdToLineItemIdMap->{$groupId}}, $lineItem->{'id'};
                    }
                }
            }
    
            push @sortedLineitemsIds, $grouIdToLineItemIdMap; # **[[Question 1]]** This will always add bundle items at the end irrespective of whether it was in starting or end.
    
    现在这将产生sortedLineitemsIds=>

        $VAR1 = [
         'id1',
         'id5',
         {
          '45D' => [
            'id4:',
            'id2:'
           ],
          '56A' => [
            'id6:',
            'id3:'
          ]
         }
       ];
    
    第2条代码

        foreach my $Id (@sortedLineitemsIds) {
            if(determineIfSingleIdOrMapOfGroupId) { #**[[Question 2]]**
                my $lineItem = grep @lineItems with $Id; #**[[Question 3]]**
                push @sortedLineItems, $lineItem;
            } else {
                 my $listOfLineItemsForGroupId = $sortedLineitemsIds->{$Id};
                 foreach groupLineItemId (@$listOfLineItemsForGroupId) {
                     my $lineItem = grep @lineItems with groupLineItemId; #**[[Question 3]]**
                     push @sortedLineItems, $lineItem;
                 }
            }
        }
    
    我现在有3个问题在代码的不同位置标记:

  • 问题1->这里我不想更改 项目。把他们分组。但我所做的是它推动了所有的 映射中组的行项目,我将在 环我怎样才能在循环中做到这一点以保持秩序
  • 问题2->我如何确定它是否是单个Id(非 bundle id)或groupID(基本上是包含 LineItemId)
  • 问题3->我如何根据 “id”并获取相应的行项目

  • 你说你不想改变物品的顺序,但这显然不是真的。我想你的意思是:

    我想保留项目的相对顺序,这些项目要么是独立的,要么是它们组中的第一个

    这确实可以在O(N)中完成

    我们要建造这个:

    my@grouped=(
    [$lineItem_id1],
    [$lineItem_id4,$lineItem_id2],
    [$lineItem_id6,$lineItem_id3],
    [$lineItem_id5],
    );
    
    为了实现这一点,我们将使用以下算法:

  • 对于每个项目,
  • 如果项目是独立的,
  • 将其添加到
    @grouped
  • 否则,,
  • 查找以前是否遇到过项目的组
  • 如果该项目是我们以前从未遇到过的组的一部分,
  • 如果是父母,
  • 将其添加到现有组的开头
  • 否则,,
  • 将其添加到现有组的末尾
  • 否则,,
  • 从项目创建新组
  • 将新组添加到
    @grouped
  • 将新组添加到查找哈希
  • 最后,我们将得出以下结论:

    my$group_45D=[$lineItem_id4,$lineItem_id2];
    我的$group_56A=[$lineItem_id6,$lineItem_id3];
    我的%groups=(
    “45D”=>$group_45D,
    “56A”=>$group_56A,
    );
    我的@grouped=(
    [$lineItem_id1],
    $45D组,
    $group_56A,
    [$lineItem_id5],
    );
    
    解决方案:

    my@grouped;
    {
    我的%组;
    对于我的$lineItem(@$lineItems){
    if(my$groupId=$lineItem->{groupId}){
    if(!$groups{$groupId}){
    push@grouped,$groups{$groupId}=[];
    }
    如果($lineItem->{isParent}){
    取消移位@{$groups{$groupId},$lineItem;
    }否则{
    push@{$groups{$groupId}},$lineItem;
    }
    }否则{
    推送@grouped,[$lineItem];
    }
    }
    }
    
    最后,我们只需要将列表展平

    my@ordered=map{@$}@grouped;
    

    已测试。

    此处您不能将组的父项作为该组的第一项。我们需要检查它是否是父对象,然后在前面添加。和id4一样,虽然它在相对顺序上排在后面,但由于它的父代在id2之前。我们如何才能做到这一点?另外,你是说我们可以在一个循环中完成这项工作?分组变量是映射吗?那我们可以用“推”操作符吗?我看到你正在使用“分组”作为地图和列表。不确定你是否能在perl中做到这一点。很抱歉提出一些愚蠢的问题,但我对perl.Correct非常陌生。如果“%grouped”是一个散列,我在这里得到一个错误:push@grouped,$grouped{$groupID}=[];另外,在哪里使用了%组?我在这里感到困惑。我们可以在聊天中进行讨论吗?