在链式调用中访问结果数组大小

时间:2015-03-26 15:59:04

标签: ruby method-chaining

我正在尝试编写一个单行程序来从VirtualBox的主机接口列表的输出创建一个哈希。它看起来像这样

Name:            vboxnet0
GUID:            77777777-6666-4444-8888-020227202302
DHCP:            Disabled
IPAddress:       192.168.42.1
NetworkMask:     255.255.255.0
IPV6Address:
IPV6NetworkMaskPrefixLength: 0
HardwareAddress: 0a:00:27:00:00:00
MediumType:      Ethernet
Status:          Up
VBoxNetworkName: HostInterfaceNetworking-vboxnet0

Name:            vboxnet1
GUID:            77777777-6666-4444-8888-020227202301
DHCP:            Disabled
IPAddress:       172.16.0.1
NetworkMask:     255.255.255.0
IPV6Address:
IPV6NetworkMaskPrefixLength: 0
HardwareAddress: 0a:00:27:00:00:01
MediumType:      Ethernet
Status:          Up
VBoxNetworkName: HostInterfaceNetworking-vboxnet1

我试过了:

Hash[*`VBoxManage list hostonlyifs`.split("\n").reject(&:empty?).collect {|s| s.split(/:\ */)}.flatten(1)]

结果是:

=> {"Name"=>"vboxnet1", "GUID"=>"786f6276-656e-4174-8000-0a0027000001", "DHCP"=>"Disabled", "IPAddress"=>"172.16.0.1", "NetworkMask"=>"255.255.255.0", "IPV6Address"=>"IPV6NetworkMaskPrefixLength", "0"=> "HardwareAddress", "0a"=>"00", "27"=>"00", "00"=>"01", "MediumType"=>"Ethernet", "Status"=>"Up", "VBoxNetworkName"=>"HostInterfaceNetworking-vboxnet1"}

几乎是我想要的,但仅限于第一个界面。我在想:“好吧,将数组切成两半并将每一半转换为哈希!”。

我的问题是如何获得flatten方法返回的Array的大小,并在slice方法的参数中使用它而不将其赋值给变量等?

我的意思是:

`VBoxManage list hostonlyifs`.split("\n").reject(&:empty?).collect {|s| s.split(/:\ */)}.flatten(1).slice(0..>>>how_to_access_result_object_of_flatten_here<<<.size/2)

我不是那种经验丰富的Ruby,所以很抱歉,如果问题很明显,但我尝试了很多谷歌搜索无济于事。

编辑:?closure / lambda中split的正则表达式?传递给collect是不对的,因为它只返回一个字符串(应该是两个用于哈希转换才能工作),如果在冒号之后只有空格,那么以IPV6Address:开头的行就是这种情况(在示例中不可见)。我将其更改为split(/:\ /),现在可以正常工作了。需要空间,因为只使用冒号也会分割MAC地址。

2 个答案:

答案 0 :(得分:1)

除非有一些我从未见过的特殊的Ruby巫术,否则我很确定简单的答案就是你不能。

但是,下一个最好的方法(而不是将数组赋值给变量)是扩展Array类并编写一个额外的方法,如下所示:

class Array
  def flatten_and_slice
    flattened_result = self.flatten(1)
    self.slice(0..flattened_result.size/2)
  end
end

然后你只需要调用你的新方法。

`VBoxManage list hostonlyifs`.split("\n").reject(&:empty?).collect {|s| s.split(/:\ */)}.flatten_and_slice

答案 1 :(得分:1)

您可以按^$拆分输出并选择所需的界面:

text = `VBoxManage list hostonlyifs`
Hash[*text.split(/^$/)[0].split(/\n/).flat_map {|line| line.split(":", 2).map(&:strip) }]

text.split(/^$/)[0]将文本分割为空行并接受第一个界面。然后,我们只需将该文本解析为散列,然后将其拆分为单独的行,分成[key,value]对,并将其映射为Hash。这给出了如下输出:

{
                           "Name" => "vboxnet0",
                           "GUID" => "77777777-6666-4444-8888-020227202302",
                           "DHCP" => "Disabled",
                      "IPAddress" => "192.168.42.1",
                    "NetworkMask" => "255.255.255.0",
                    "IPV6Address" => "",
    "IPV6NetworkMaskPrefixLength" => "0",
                "HardwareAddress" => "0a:00:27:00:00:00",
                     "MediumType" => "Ethernet",
                         "Status" => "Up",
                "VBoxNetworkName" => "HostInterfaceNetworking-vboxnet0"
}

如果要生成一个哈希数组,每个接口一个,分割文本,然后将每个文本块映射到哈希:

text.split(/^$/).map {|chunk| Hash[*chunk.split(/\n/).flat_map {|line| line.split(":", 2).map(&:strip) }] }

导致:

[
    [0] {
                               "Name" => "vboxnet0",
                               "GUID" => "77777777-6666-4444-8888-020227202302",
                               "DHCP" => "Disabled",
                          "IPAddress" => "192.168.42.1",
                        "NetworkMask" => "255.255.255.0",
                        "IPV6Address" => "",
        "IPV6NetworkMaskPrefixLength" => "0",
                    "HardwareAddress" => "0a:00:27:00:00:00",
                         "MediumType" => "Ethernet",
                             "Status" => "Up",
                    "VBoxNetworkName" => "HostInterfaceNetworking-vboxnet0"
    },
    [1] {
                               "Name" => "vboxnet1",
                               "GUID" => "77777777-6666-4444-8888-020227202301",
                               "DHCP" => "Disabled",
                          "IPAddress" => "172.16.0.1",
                        "NetworkMask" => "255.255.255.0",
                        "IPV6Address" => "",
        "IPV6NetworkMaskPrefixLength" => "0",
                    "HardwareAddress" => "0a:00:27:00:00:01",
                         "MediumType" => "Ethernet",
                             "Status" => "Up",
                    "VBoxNetworkName" => "HostInterfaceNetworking-vboxnet1"
    }
]