|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » PowerShell - Выбор групп строк из массива по разделителю |
|
PowerShell - Выбор групп строк из массива по разделителю
|
Новый участник Сообщения: 25 |
Профиль | Отправить PM | Цитировать Добрый день. Имеется массив строк
В нем есть т.к. разделители групп данных, в данном случае это '0' Задача: Выделить эти группы данных для дальнейшей работы в отдельный двумерный массив или хеш-таблицу В итоге должно получиться аналогично этой структуре split тут не поможет так понимаю... Пока только такая идея - использовать функцию для поиска индексов этого разделителя function findinarr ($mass, $value) { for ($i=0; $i -lt $mass.count;$i++) { if($mass[$i] -eq $value){$i} } } А потом как-то прогнать исходный массив, с выбором строк 0-3, 4-5 и передать это в новый массив. А Затем уже в нем split сделать окончательный Как-то неуклюже.. и затратно будет, при наличии большого кол-ва строк Есть какой-то "правильный" и оптимальный способ решения? |
|
Отправлено: 21:24, 16-02-2023 |
Ветеран Сообщения: 1754
|
Кривовато, но вроде работает:
|
Отправлено: 23:30, 16-02-2023 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Новый участник Сообщения: 25
|
Профиль | Отправить PM | Цитировать Понятно, спасибо.
Была мысль собрать -join. А если там будет условно 100 000 строк... Могут быть проблемы с производительностью |
Отправлено: 00:33, 17-02-2023 | #3 |
fascinating rhythm Сообщения: 6530
|
Профиль | Отправить PM | Цитировать Может, так?
$mass2 = [System.Collections.ArrayList]@() -join $mass1 -split '0' -match '.' |% { $mass2.add(("$_").ToCharArray()) } PS C:\WINDOWS\system32> $mass2.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True ArrayList System.Object PS C:\WINDOWS\system32> $mass2[0] 1 2 3 PS C:\WINDOWS\system32> $mass2[0].GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Char[] System.Array |
------- Отправлено: 09:13, 17-02-2023 | #4 |
Crazy Сообщения: 1182
|
Профиль | Отправить PM | Цитировать |
|
------- Отправлено: 11:05, 17-02-2023 | #5 |
Crazy Сообщения: 1182
|
Профиль | Отправить PM | Цитировать Цитата ntdll.dll:
|
|
------- Отправлено: 12:35, 17-02-2023 | #6 |
Crazy Сообщения: 1182
|
Профиль | Отправить PM | Цитировать Цитата ntdll.dll:
Тем более, что поправить - не проблема же. Но там ещё есть другая проблема... при значительном увеличении количества элементов массива (точное число не назову, но на 10000 уже спотыкается ), метод с заменой регулярками попросту захлебнется от этого количества... А вот метод со списками, вполне быстрый... Цитата ntdll.dll:
Цитата ntdll.dll:
Цитата ntdll.dll:
Да и просто озвучивание - ничего не показывает... важно только решение, но где оно? |
||||
------- Отправлено: 17:24, 17-02-2023 | #7 |
Crazy Сообщения: 1182
|
Профиль | Отправить PM | Цитировать Цитата solonenko:
Цитата ntdll.dll:
# тесты различных способов разделения массива по разделителю # namespace - для использования варианта с list: using namespace System.Collections.Generic $splt = "0" #$arr = @(0,0,0,1,22,33,0,0,0,444,555,550,606,0,44,55,0,1,2,3,4,5,0,8,9,0) $arr = @(0,0,0) $arr += 1..100000|%{get-random -min 0 -max 100} write-host Вариант с replace, split и for -for cyan measure-command{ $tmp = [string]$arr while ($tmp[0] -match " |$splt" -or $tmp[-1] -match " |splt"){ $tmp = $tmp.trim($splt).trim() } $a = $tmp -replace " ($splt )+"," $splt " -split " $splt " $b = @() for ($i=0;$i -lt $a.count;$i++){ $b += ,[int[]](($a[$i].trim() -split' ').foreach{[int]"$_"}) } } write-host Кол-во элементов: $($b.count) -for green write-host Первый элемент: $($b[0]) -for red "====" write-host Вариант с replace и iex -for cyan measure-command{ $tmp = [string]$arr while ($tmp[0] -match " |$splt" -or $tmp[-1] -match " |$splt"){ $tmp = $tmp.trim($splt).trim() } #$b = iex "@($(($$="$a 0" -replace '(?:\s)?\b0\b(?:\s)?', '),(').Substring(2,$$.Length-4) -replace '\s', ','))" $b = iex "@($((('('+$tmp+')') -replace "\s($splt\s)+",'),(') -replace '\s',','))" } write-host Кол-во элементов: $($b.count) -for green write-host Первый элемент: $($b[0]) -for red "====" write-host Вариант с replace и скриптблоком -for cyan measure-command{ $tmp = [string]$arr while ($tmp[0] -match " |$splt" -or $tmp[-1] -match " |splt"){ $tmp = $tmp.trim($splt).trim() } $b = &([scriptblock]::create([string]$((('('+$tmp+')') -replace " ($splt )+",'),(') -replace ' ',','))) } write-host Кол-во элементов: $($b.count) -for green write-host Первый элемент: $($b[0]) -for red "====" write-host Вариант с foreach, switch и array -for cyan measure-command{ $a,$b,$cnt = @(),@(),0 $arr.foreach{ switch ($_){ $splt {if ($cnt -and $t -ne $splt){$b += ,$a;$a = @()}} default {$a += $_} } $cnt++ $t = $_ if($_ -and $arr.count -eq $cnt){$b += ,$a} } } write-host Кол-во элементов: $($b.count) -for green write-host Первый элемент: $($b[0]) -for red "====" write-host Вариант с foreach и list -for cyan measure-command{ $res, $tmp =[List[Int32[]]]::new(),[List[Int32]]::new() foreach ($val in $arr) { if ($tmp -and $val -eq $splt -and $z -ne $splt) { $res.Add($tmp.ToArray()) $tmp.Clear() #continue } elseif ($val -ne $splt){$tmp.Add($val)} $z = $val } if ($tmp){$res.Add($tmp.ToArray())} #if (!$res[0]) {[void]$res.Remove($res[0])} $res = $res.ToArray() } write-host Кол-во элементов: $($res.count) -for green write-host Первый элемент: $($res[0]) -for red "====" Изначально формируется один массив в 100000 элементов, причем на все варианты - результаты идентичны, но скорострельность отличается... |
||
------- Последний раз редактировалось YuS_2, 18-02-2023 в 13:57. Отправлено: 13:52, 18-02-2023 | #8 |
fascinating rhythm Сообщения: 6530
|
Профиль | Отправить PM | Цитировать +=, кстати - довольно коварная штука. По умолчанию массив в PS неизменяемый (immutable), поэтому при += создаётся новый массив. Если элементов много, то падение производительности после определённого кол-ва элементов становится очень большим.
Есть ArrayList, который изменяемый и в него можно именно добавлять элементы, а не пересоздавать массив каждый раз. https://adamtheautomator.com/powersh...ith_PowerShell |
------- Отправлено: 14:29, 18-02-2023 | #9 |
Crazy Сообщения: 1182
|
Профиль | Отправить PM | Цитировать Цитата DJ Mogarych:
У меня тут даже тест есть... $cnt = 30000 measure-command{ $arr1 = @() for ($i=0;$i -le $cnt;$i++) { $arr1 += "test $i" } } measure-command{ $arr2 = new-object system.collections.generic.list[system.string] for ($i=0;$i -le $cnt;$i++) { $arr2.add("test $i") } } measure-command { $arr3 = new-object system.text.stringbuilder for ($i=0;$i -le $cnt;$i++){ $null = $arr3.append("test $i") } } Хотя, почему бы не использовать, раз уж есть такой тип массивов... в любом случае, хоть и ненамного, но быстрее. |
|
------- Отправлено: 14:45, 18-02-2023 | #10 |
Участник сейчас на форуме | Участник вне форума | Автор темы | Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
CMD/BAT - [решено] Разбить txt на части по разделителю | Viktor99 | Скриптовые языки администрирования Windows | 7 | 31-07-2022 15:13 | |
C/C++ - [решено] Удаление строк динамического массива | alexprom65 | Программирование и базы данных | 1 | 24-12-2014 22:47 | |
CMD/BAT - Выбор данных из массива. | subuday77 | Скриптовые языки администрирования Windows | 1 | 25-12-2013 06:13 | |
[решено] Вывод массива строк в одном окне сообщения (MsgBox) | support23 | AutoIt | 4 | 29-10-2012 18:26 | |
С/С++ | Выбор 10 случайных элементов из массива | Vovius | Программирование и базы данных | 5 | 29-08-2006 19:37 |
|