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

Accessing result array size in chained call

我正在尝试编写一个单行代码来从 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"}

几乎是我想要的,但仅限于第一个界面。我在想:"Okay, slice the array into half and convert each half to a hash!".

我的问题是如何获取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 方面经验不足,如果问题很明显,我很抱歉,但我尝试了很多谷歌搜索都无济于事。

编辑:split 在 ?closure/lambda?传递给 collect 是不正确的,因为它 returns 只有一个字符串(对于散列转换来说应该是两个字符串)如果在冒号之后只有 spaces 就是这种情况以 IPV6Address: 开头的行(示例中不可见)。我将其更改为 split(/:\ /),现在可以使用了。 space 是必需的,因为仅使用冒号也会拆分 MAC 地址。

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

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

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

您可以将输出拆分为 ^$ 并获取您想要的接口:

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

text.split(/^$/)[0] 将文本拆分为空行,取第一个界面。然后,我们只需将该文本拆分成单独的行,拆分成 [key, value] 对,并将其映射到哈希中,即可将其解析为哈希。这给出如下输出:

{
                           "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"
    }
]