Построчное чтение файла и работа с элементами строки
Здравствуйте! Никак не получается разобраться: Нужно прочитать текстовый файл, и в каждой строке попарно заменить слова между собой (1-е со 2-м, 3-е с 4-м и т.д)
|
было бы неплохо увидеть пример строки, а еще лучше пример файла.
Ну и так, немного на вентилятор:
чем разделяются "слова";
что делать если количество слов в строке нечетное;
какая кодировка у файла;
чем строки заканчиваются;
куда, наконец, резльтат записывать?
|
По рабоче-крестьянски:
Скрытый текст
Код:
Get-Content -Path 'C:\Мои проекты\0322\0001.txt' |`
ForEach-Object -Process {
$aWords = $_.Split()
$iCount = $aWords.Count - $aWords.Count % 2
for($i = 0; $i -lt $iCount; $i = $i + 2) {
$sWord = $aWords[$i]
$aWords[$i] = $aWords[$i + 1]
$aWords[$i + 1] = $sWord
}
$aWords -join ' '
}
Полагаю, можно быстрее сделать замену регуляркой.
|
Код:
$text = 'один два три четыре пять'
$arr = $text.Split()
$n = [Collections.ArrayList] @()
for ($i = 0; $i -lt $arr.Count; $i++)
{
switch ( $i % 2 )
{
1 { $n.Insert(($i-1),$arr[$i]) }
0 { $n.Insert($i,$arr[$i]) }
}
}
$n -join ' '
|
greg zakharov |
05-10-2020 21:15 2935630 |
Длина строк (количество слов в строке), как и пунктуация, действительно автором темы не были оговорены. А так можно подбросить решение в "функциональном" стиле.
Код:
$text = @'
два один четыре три пять
это а длинная просто строка тестовая
'@
$text | ConvertFrom-Csv -Delimiter ' ' -Header (($arr =
1..($text.Split("`n") | Sort-Object Length -Bottom 1 | Measure-Object -Word).Words
)) | Select-Object -Property ([String[]]$arr.ForEach{$_ + ($_ % 2 -eq 0 ? -1 : 1)}) |
ConvertTo-Csv -Delimiter ' ' -UseQuotes 0 | Select-Object -Skip 1
Что касается скорости и текстовых файлов (больших в частности), лучше воспользоваться SQLite.
|
greg zakharov |
10-10-2020 22:39 2936056 |
Одно из возможных решений при наличии пунктуации в тексте - токенизация на манер того, как это реализовано в PSParser.
Код:
@'
каждый И в, вечер назначенный час,
(это Иль снится только мне?)
стан Девичий, схваченный шелками,
туманном В окне движется.
медленно И, меж пройдя пьяными,
без Всегда одна, спутников,
духами Дыша туманами и,
садится Она окна у.
'@.Split("`n").ForEach{
$i, $str = 0, $_
$arr = ($str -split '(\p{L}+|\p{P})(?:\s+)?').Where{$_}.ForEach{
[PSCustomObject]@{
Type = $_ -match '\p{P}' ? 'Punctuation' : 'Word'
Index = ++$i
Value = $_
}
}
$w = $arr.Where{$_.Type -eq 'Word'}
$sz = $w.Count % 2 -eq 0 ? $w.Count : $w.Count - 1
for ($i = 0; $i -lt $sz; $i += 2) {
$w[$i].Index, $w[$i + 1].Index = $w[$i + 1].Index, $w[$i].Index
}
($w + $arr.Where{$_.Type -eq 'Punctuation'} |
Sort-Object Index).Value -join ' ' -replace '\s(\p{P})', '$1'
}
При работе с потоками производительность повысится, но не сравнится по скорости с использованием указателей (правда для этого нужно знать опкоды IL, а объяснять каждый из них не хочется, поэтому примера не последует).
|
Время: 20:40.
© OSzone.net 2001-