将Perl哈希合并到一个数组中并循环遍历它

时间:2017-07-19 10:54:02

标签: arrays perl loops

我正在为cPanel创建一个Perl插件,该插件必须获取用户帐户中的所有域并将其显示在HTML select字段中。最初,我是一名PHP开发人员,所以我很难理解Perl的一些逻辑。我知道cPanel插件也可以用PHP编写,但对于这个插件,我只限于Perl。

这是我从cPanel获取数据的方式:

my @user_domains = $cpliveapi->uapi('DomainInfo', 'list_domains');
@user_domains = $user_domains[0]{cpanelresult}{result}{data};

这就是使用print Dumper @user_domains

的样子
$VAR1 = {
    'addon_domains' => ['domain1.com', 'domain2.com', 'domain3.com'],
    'parked_domains' => ['parked1.com', 'parked2.com', 'parked3.com'],
    'main_domain' => 'main-domain.com',
    'sub_domains' => ['sub1.main-domain.com', 'sub2.main-domain.com']
};

我希望数据看起来像这样(感谢@simbabque):

@domains = qw(domain1.com domain2.com domain3.com main-domain.com parked1.com parked2.com parked3.com);

所以,我想排除sub_domains并将其他人合并到一个单维数组中,这样我就可以用一个循环遍历它们。过去几天我一直在努力,听起来这是一个非常简单的任务,但我无法绕过它。

2 个答案:

答案 0 :(得分:1)

这不符合你的想法。 {}是匿名哈希构造函数,所以你要创建一个带有哈希的1元素数组。

你可能想要:

use Data::Dumper;

my %user_domains = (
    'addon_domains' => ['domain1.com', 'domain2.com', 'domain3.com'],
    'parked_domains' => ['parked1.com', 'parked2.com', 'parked3.com'],
    'main_domain' => 'main-domain.com',
    'sub_domains' => ['sub1.main-domain.com', 'sub2.main-domain.com'],
);

print Dumper \%user_domains;

此时,“其他”数组元素可以通过双循环迭代:

foreach my $key ( keys %user_domains ) { 
    if ( not ref $user_domains{$key} ) { 
        print $user_domains{$key},"\n";
        next;
    }
    foreach my $domain (  @{$user_domains{$key}} ) {
        print $domain,"\n";
    }
}

或者如果你真的想要'压扁'你的哈希:

my @flatten = map { ref $_ : @$_ ? $_ } values %user_domains;
print Dumper \@flatten;

(您需要ref测试,因为没有它,非数组main-domain将无法正常工作)

因此,为了保持一致性,您可能会更好:

my %user_domains = (
    'addon_domains' => ['domain1.com', 'domain2.com', 'domain3.com'],
    'parked_domains' => ['parked1.com', 'parked2.com', 'parked3.com'],
    'main_domain' => ['main-domain.com'],
    'sub_domains' => ['sub1.main-domain.com', 'sub2.main-domain.com'],
);

答案 1 :(得分:1)

你需要这样的东西

如果您发现<?xml version="1.0"?> <!-- dpcontrols\UseIList.mxml --> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" initialize="initData();"> <s:layout> <s:VerticalLayout/> </s:layout> <fx:Script> <![CDATA[ import mx.collections.*; // The data provider is an Array of Strings public var myArray:Array = ["AZ", "MA", "MZ", "MN", "MO", "MS"]; // Declare an ArrayList that represents the Array. [Bindable] public var myAL:ArrayList; //Initialize the ArrayList. public function initData():void { myAL = new ArrayList(myArray); } // The function to change the collection, and therefore // the Array. public function changeCollection():void { // Get the original collection length. var oldLength:int=myAL.length; // Remove the invalid first item, AZ. var removedItem:String=String(myAL.removeItemAt(0)); // Add ME as the second item. (ILists used 0-based indexing.) myAL.addItemAt("ME", 1); // Add MT at the end of the Array and collection. myAL.addItem("MT"); // Change the third item from MZ to MI. myAL.setItemAt("MI", 2); // Get the updated collection length. var newLength:int=myAL.length; // Get the index of the item with the value ME. var addedItemIndex:int=myAL.getItemIndex("ME"); // Get the fifth item in the collection. var index4Item:String=String(myAL.getItemAt(4)); // Display the information in the TextArea control. ta1.text="Start Length: " + oldLength + ". New Length: " + newLength; ta1.text+=".\nRemoved " + removedItem; ta1.text+=".\nAdded ME at index " + addedItemIndex; ta1.text+=".\nThe item at index 4 is " + index4Item + "."; // Show that the base Array has been changed. ta1.text+="\nThe base Array is: " + myArray.join(); } ]]> </fx:Script> <s:ComboBox id="myCB" dataProvider="{myAL}"/> <s:TextArea id="ta1" height="75" width="300"/> <s:Button label="rearrange list" click="changeCollection();"/> </s:Application> 的副本不包含List::Util,那么您可以升级模块或使用此定义

uniq

从您的转储中,sub uniq { my %seen; grep { not $seen{$_}++ } @_; } 调用返回对哈希的引用。这进入uapi,然后深入到结构中,将$cp_response哈希引用提取到data

$data从哈希中删除子域信息。

您想要的列表是delete引用的哈希的,因此我将其提取出来。如果列表中有多个域,则这些值是对字符串的引用,如果只有一个域,则为简单字符串

$data通过取消引用数组引用或直接传递字符串,将所有域名转换为单个列表。这就是map正在做的事情。 FInally ref() ? @$_ : $_删除多次出现的同名

uniq

输出

use List::Util 'uniq';

my $cp_response = $cpliveapi->uapi('DomainInfo', 'list_domains');
my $data        = $cp_response->{cpanelresult}{result}{data};

delete $data->{sub_domains};

my @domains = uniq map { ref() ? @$_ : $_ } values %$data;