2017-02-18 39 views
0

Имея следующий фрагмент кода:Как взять карту в конкретный элемент после карты и сплит?

import std.algorithm; 
import std.array : split; 
import std.stdio; 
import std.file; 
import std.range; 

void main(string[] args) 
{ 
    string filename = "file.log"; 
    string term = "action"; 
    auto results = File(filename, "r") 
        .byLine 
        .filter!(a => canFind(a, term)) 
        .map!(a => splitter(a, ":")); 
        // now how to take only first part of split? up to first ':'? 

    foreach (line; results) 
     writeln(line); 
} 

Я заинтересован только в первой части после раскола операции (или какой-либо другой операции, которая могла бы быть более эффективным - просто найти первый : и извлечь все символы до него).

Я пытался что-то вроде:

.map!(a => a[0]) 

после раскола, но я получил ошибку

main.d(37): Error: no [] operator overload for type Result 
/usr/include/dmd/phobos/std/algorithm/iteration.d(488):  instantiated from here: MapResult!(__lambda4, MapResult!(__lambda3, FilterResult!(__lambda2, ByLine!(char, char)))) 
main.d(37):  instantiated from here: map!(MapResult!(__lambda3, FilterResult!(__lambda2, ByLine!(char, char)))) 

ответ

1

Использование until ,

.map!(a => a.until(':'));

group «s сравнение по умолчанию a == b, который не работает на ленивых Untils. Для того, чтобы использовать его с group, вам необходимо пройти сравнение, который работает, который будет equal:

.map!(a => a.until(':')) 
    .group!equal 
    ... 
+0

вместо '.map! (A => splitter (a,": ").) 'с' .map! (a => a.until (':')) 'как-то испортил мои результаты: я получаю несортированные данные (при сортировке в качестве ввода). – Patryk

+0

Это может быть вызвано нестабильностью результата byLine, вы можете попробовать 'a => a.idup.until (':')' – weltensturm

+0

То же самое:/Полный код фрагмента https://dpaste.dzfl.pl/d2cc511bd7cb – Patryk

2

Вы можете использовать std.algorithm.findSplitAfter:

auto results = File(filename, "r") 
        .byLine 
        .filter!(a => canFind(a, term)) 
        .map!(a => a.findSplitAfter(":")[1]); 

Другой вариант сочетает в себе find, чтобы вы к : и drop, чтобы вы мимо него: (? Какие-либо идеи, если есть что-то вроде индексации оператора помимо front)

auto results = File(filename, "r") 
       .byLine 
       .filter!(a => canFind(a, term)) 
       .map!(a => a.find(":").drop(1)); 
+0

Это не 'findSplitAfter ... [1]' 'но findSplitBefore ... [0]' Я искал для. Капля не работает, как я хотел (он извлекает часть после ':' не раньше) – Patryk

+0

В вашем вопросе «первая часть после раскола» и «найти: и вырезать все символы до него» звучат так, будто вы хотите, чтобы часть после ':' – rcorre

+0

Извините, я, возможно, использовал неправильную формулировку. Я исправил это сейчас. – Patryk

0

кажется, что я могу также использовать splitter.front

auto results = File(filename, "r") 
       .byLine 
       .filter!(a => canFind(a, term)) 
       .map!(a => splitter(a, ":").front); 

+1

'splitter' лениво оценивается и не поддерживает случайную индексацию. Вам нужно будет продвигать диапазон, используя 'drop':' splitter (a, ":"). Drop (1) .front' – rcorre