В Powershell есть лучший способ хранить / находить данные в n-мерном массиве, чем пользовательский объект

Я постоянно сталкиваюсь с необходимостью хранить данные смешанного типа в какой-то структуре для последующего поиска.

Для недавнего примера я выполняю миграцию данных и буду хранить старый UUID, новый UUID, исходную среду, целевую среду и схему для неизвестного числа записей.

Я удовлетворял эту потребность, создавая массив и вставляя объекты System.Object с элементами NoteProperty для каждого из столбцов данных.

Это выглядит как очень неуклюжий подход, но я чувствую, что меня ограничивает функциональность Powershell. Если мне нужно, например, найти все записи, которые использовали конкретную схему, я пишу цикл foreach, который вставляет каждую запись с совпадающим именем схемы во весь новый массив, который я могу вернуть. Мне бы очень хотелось, чтобы была возможность более легкого поиска всех объектов, которые содержат член, соответствующий определенному значению, изменение существующих членов и т. Д.

Существует ли лучшая встроенная структура данных, которая будет соответствовать моим потребностям, или создание пользовательского объекта является правильным решением?

Для справки, я делаю что-то вроде этого, чтобы создать свою структуру:

$objectArray= @();
foreach(thing to process){
   $tempObj = New-Object System.Object;
   $tempObj | Add-Member -MemberType NoteProperty -Name "membername" -Value xxxxx
   ....repeat for each member...
   $objectArray += $tempObj
}

Если мне нужно найти что-то в этом, я должен:

$matchingObjs = @()
foreach ($obj in $objectArray){
    if($obj.thing -eq value){$matchingObjs += $obj}
}

Это действительно отстой, и я знаю, что должен быть более элегантный способ. Я все еще довольно новичок в PowerShell, поэтому я не знаю, какие утилиты мне могут помочь. Я использую v5.

2 ответа

Решение

С PowerShell 3.0 вы можете использовать [PSCustomObject]Вот статья о различных методах создания объектов.

Также устанавливая массив, равный выходу foreach цикл будет более эффективным, чем повторное создание массива с +=,

$objectArray = foreach ($item in $collection) {
    [pscustomobject]@{
        "membername" = "xxxxx"
    }
}

Where-Object Командлет или .where() Метод выглядит так, как вам нужно во втором цикле.

$matchingObjs = $objectArray | Where-Object {$_.thing -eq "value"}

Это также звучит так, как если бы вы могли использовать Where-Object/.where() отфильтровать исходные данные и просто создать объект, который соответствует тому, что вы ищете. Например:

$matchingObjs = $InputData |
    Where-Object {$_.thing -eq "value"} |
    ForEach-Object {
        [pscustomobject]@{
            "membername" = xxxxx
        }
    }

Если ваши данные могут быть выражены в виде пар ключ-значение, то hashtable будет наиболее эффективным, смотрите about_Hash_Tables для получения дополнительной информации.

Нет встроенного способа сделать то, что вы просите. Один из способов - сегментировать ваши данные в отдельные хеш-таблицы, чтобы вы могли легко выполнять поиск по общему ключу, например, по идентификатору.

# Create a hastable for the IDs
$ids = @{};
foreach(thing to process){
    $ids.Add($uid, 'Value')
}

# Find the $uid exists
$keyExists = $ids.Keys -Contains $uid

# Find value of stored for $uid
$keyValue = $ids[$uid]

Как примечание, вам не нужно создавать Syste. Object, вы можете просто сделать это:

$objectArray = @();

gci | % {
    $objectArray += @{
        'Key1' = 'Value 1'
        'Key2' = 'Value 2'
    }
}

Если вам нужно сравнить сложные объекты, вы можете построить их с помощью @{}, а затем использовать Compare-Object для двух объектов, просто еще одна идея.

Например, он получит список файлов двух разных каталогов и скажет мне, какой файл существует или не существует между двумя каталогами:

$packages = (gci $boxStarterRepo -Recurse *.nuspec | Select-Object -ExpandProperty Name) -replace '.nuspec', ''
$packages += (gci $boxStarterPrivateRepo -Recurse *.nuspec | Select-Object -ExpandProperty Name) -replace '.nuspec', ''
$packages = $packages | Sort-Object

Compare-Object $packages $done
Другие вопросы по тегам