Ho un metodo che esegue un semplicistico "grep" tra i file, utilizzando una enumerabile di "stringhe di ricerca". (In effetti, sto facendo un molto ingenuo "Trova tutti i Riferimenti")Come rendere un C# 'grep' più funzionale usando LINQ?
IEnumerable<string> searchStrings = GetSearchStrings();
IEnumerable<string> filesToLookIn = GetFiles();
MultiMap<string, string> references = new MultiMap<string, string>();
foreach(string fileName in filesToLookIn)
{
foreach(string line in File.ReadAllLines(fileName))
{
foreach(string searchString in searchStrings)
{
if(line.Contains(searchString))
{
references.AddIfNew(searchString, fileName);
}
}
}
}
Nota: MultiMap<TKey,TValue>
è più o meno lo stesso di Dictionary<TKey,List<TValue>>
, solo evitando le NullReferenceExceptions che normalmente si incontrano.
mi hanno cercato di mettere questo in uno stile più "funzionale", usando concatenati metodi di estensione LINQ, ma non hanno capito.
Un tentativo vicolo cieco:
// I get lost on how to do a loop within a loop here...
// plus, I lose track of the file name
var lines = filesToLookIn.Select(f => File.ReadAllLines(f)).Where(// ???
E un altro (si spera preservare il nome del file questa volta):
var filesWithLines =
filesToLookIn
.Select(f => new { FileName = f, Lines = File.ReadAllLines(f) });
var matchingSearchStrings =
searchStrings
.Where(ss => filesWithLines.Any(
fwl => fwl.Lines.Any(l => l.Contains(ss))));
Ma ho ancora sembra di perdere le informazioni di cui ho bisogno.
Forse mi sto avvicinando a questo dall'angolo sbagliato? Dal punto di vista delle prestazioni, i loop dovrebbero eseguire all'incirca lo stesso ordine dell'esempio originale.
Qualche idea su come eseguire questa operazione in una rappresentazione funzionale più compatta?
Non ero a conoscenza si potrebbe usare più "da" dichiarazioni come queste. Come funziona davvero? La mia esperienza con LINQ è avvenuta esclusivamente attraverso lambda e metodi di estensione. Questo si traduce persino in metodi di estensione concatenati? –
Sì, più da clausole traducono in chiamate al metodo di estensione SelectMany. Guardalo in Reflector per vedere esattamente cosa sta succedendo. – dahlbyk
@jmitchem: ho modificato la mia risposta per rispondere alle vostre domande. –