Tuples / ArrayList пар - PullRequest
       6

Tuples / ArrayList пар

0 голосов
/ 26 января 2019

Я, по сути, пытаюсь создать список пар, который оказывается невероятно трудным

Обратите внимание, прежде чем кто-либо упоминает Hashtables, что будут дубликаты, которые меня не волнуют.

ДляНапример, если я сделаю

$b = @{"dog" = "cat"}

, я получу

Name                           Value
----                           -----
dog                            cat

, что хорошо.Тем не менее, я не могу добавить подобные

$b += @{"dog" = "horse"}

Элемент уже был добавлен.Ключ в словаре: 'собака' Добавляемый ключ: 'собака'

Я просто пытаюсь создать таблицу данных , которую я могу добавить к , используя что-то вроде .Add() или +=.

Ответы [ 4 ]

0 голосов
/ 29 января 2019

Благодаря mklement0, как показано ниже, возможно, самое простое решение

$b = , @{ dog = "cat"} 
$b += @{ dog = "horse"}

И метод Persistent13 также дает легкий маршрут

$ht = @{foo='bar'}
$list = [System.Collections.Generic.List[hashtable]]::new()
$list.Add($ht)
$list.Add($ht)
$list.Add($ht)
$list

Полагаю, меня просто удивило, что не былоболее укоренившийся способ получить, как мне кажется, довольно простой / стандартный тип объекта

0 голосов
/ 26 января 2019

Полезный ответ Persistent13 предлагает эффективное и действенное решение, хотя и немного неясное.

Создание массива хеш-таблиц является самым простым решением, хотя важно отметить, что "расширение" массива подразумевает неявное воссоздание его, учитывая, что массивы являются структурами данных фиксированного размера , которая может стать проблемой производительности при многих итерациях:

# Using array-construction operator ",", create a single-element array
# containing a hashtable
$b = , @{ dog = "cat"} 

# "Extend" array $b by appending another hashtable.
# Technically, a new array must be allocated that contains the original array's
# elements plus the newly added one.
$b += @{ dog = "horse"}

В этой проблеме GitHub обсуждается потенциальное будущее усовершенствование, позволяющее PowerShell изначально поддерживать эффективно расширяемый тип данных в виде списка или даже равный по умолчанию для такого типа данных. (Начиная с Windows PowerShell v5.1 / PowerShell Core 6.2.0, PowerShell по умолчанию использует массивы фиксированного размера типа [object[]]).

0 голосов
/ 26 января 2019

Если вам нужен список кортежей, я бы порекомендовал создать список из кортежей :

$list = @()

$tuple1 = New-Object 'Tuple[String,String]' 'dog', 'cat'
$tuple2 = New-Object 'Tuple[String,String]' 'dog', 'horse'

$list += $tuple1
$list

# Output:
#
# Item1 Item2 Length
# ----- ----- ------
# dog   cat        2

$list += $tuple2
$list

# Output:
#
# Item1 Item2 Length
# ----- ----- ------
# dog   cat        2
# dog   horse      2

Обратите внимание, что в этом примере $list - это обычный массив, что означаетчто, как указал @ mklement0 в своем ответе, добавление к нему с помощью оператора присваивания += создаст массив с размером, увеличенным на 1, поместит новый элемент в новый пустой слот, затемзаменить оригинальный массив.Для небольшого числа операций добавления это обычно не представляет большой проблемы, но с увеличением количества операций добавления влияние на производительность становится значительным.

Использование ArrayList вместо простого массива позволяет избежать этой проблемы:

$list = New-Object Collections.ArrayList

$tuple1 = New-Object 'Tuple[String,String]' 'dog', 'cat'
$tuple2 = New-Object 'Tuple[String,String]' 'dog', 'horse'

$list.Add($tuple1) | Out-Null
$list

# Output:
#
# Item1 Item2 Length
# ----- ----- ------
# dog   cat        2

$list.Add($tuple2) | Out-Null
$list

# Output:
#
# Item1 Item2 Length
# ----- ----- ------
# dog   cat        2
# dog   horse      2

Метод Add() объектов ArrayList выводит индекс, к которому был добавлен элемент.Out-Null подавляет вывод, который в большинстве случаев нежелателен.Если вы хотите работать с этими индексными числами, вы можете собрать их в переменную вместо того, чтобы отбрасывать их ($i = $list.Add($t1)).

Если вы хотите избежать необходимости указывать тип нового кортежа все времяможет обернуть его в многократно используемую функцию, например:

function New-Tuple {
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateCount(2,2)]
        [string[]]$Values
    )

    New-Object 'Tuple[String,String]' $Values
}

$tuple1 = New-Tuple 'dog', 'cat'
$tuple2 = New-Tuple 'dog', 'horse'

или, более общим образом, например:

function New-Tuple {
    Param(
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [ValidateCount(2,20)]
        [array]$Values
    )

    Process {
        $types = ($Values | ForEach-Object { $_.GetType().Name }) -join ','
        New-Object "Tuple[$types]" $Values
    }
}

$tuples = ('dog', 'cat'), ('dog', 'horse') | New-Tuple
0 голосов
/ 26 января 2019

Я считаю, что список хеш-таблиц должен выполнить то, что вы хотите.

$ht = @{foo='bar'}
$list = [System.Collections.Generic.List[hashtable]]::new()
$list.Add($ht)
$list.Add($ht)
$list.Add($ht)
$list
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...