Почему фильтр не работает в списке строк - PullRequest
1 голос
/ 27 мая 2019

Я пытаюсь написать код для чтения текстового файла и отфильтровать те строки, которые имеют оба элемента поиска:

import std.stdio;
import std.string; 
import std.file : readText;
import std.algorithm; 

void main(){
    string[] srchitems = ["second", "pen"];  // to search file text for lines which have both these; 
    auto alltext = readText("testing.txt");
    auto alllist = alltext.split("\n");  
    foreach(str; srchitems){
        alllist = alllist.filter!(a => a.indexOf(str) >= 0);    // not working ;
    }
    writeln(alllist); 
}

Однако, это не работает и выдает эту ошибку:

$ rdmd soq_filter.d 
soq_filter.d(11): Error: cannot implicitly convert expression filter(alllist) of type FilterResult!(__lambda1, string[]) to string[]
Failed: ["/usr/bin/dmd", "-v", "-o-", "soq_filter.d", "-I."]

Следующая строка с приведением также не работает:

    alllist = cast(string[]) alllist.filter!(a => a.indexOf(str) >= 0);     // not working ;

Ошибка:

Error: cannot cast expression filter(alllist) of type FilterResult!(__lambda1, string[]) to string[]

Где проблема и как ее можно решить? Спасибо.

1 Ответ

4 голосов
/ 27 мая 2019

Как вы уже поняли, возвращаемое значение из filter - это не массив, а настраиваемый диапазон. Возвращаемое значение filter на самом деле является ленивым диапазоном, поэтому, если вы используете только первые несколько элементов, будут рассчитаны только эти элементы. Чтобы преобразовать ленивый диапазон в массив, вам нужно будет использовать std.array.array:

import std.array : array;
alllist = alllist.filter!(a => a.indexOf(str) >= 0).array;

В вашем случае это, кажется, работает хорошо. Однако, слегка реструктурировав свой код, вы получите более идиоматическое решение:

import std.stdio;
import std.string;
import std.file : readText;
import std.algorithm;
import std.array;

void main() {
    string[] srchitems = ["second", "pen"];
    auto alltext = readText("testing.txt");
    auto alllist = alltext.split("\n");
    auto results = alllist.filter!(a => srchitems.any!(b => a.indexOf(b) >= 0));
    writeln(results);
}

В приведенном выше коде мы используем результат filter напрямую, а не преобразуем его в массив.

...