2015-11-17 2 views
0

Я хочу написать функцию, которая фильтрует файлы в каталоге. Полученный путь метода, список токенов, которые должен содержать файл, и список токенов, которые не должны находиться в файле.Check String содержит все элементы в списке, используя Linq и нечувствительность к регистру

мой код выглядит так:

private String[] enumerateFilesByFilter(String path, List<String> contain, List<String> notContain) 
{ 
    String[] files = Directory.GetFiles(path).Where(f => (contain.All(f.Contains)) && (!notContain.Any(f.Contains))).ToArray(); 
    //String[] files = Directory.GetFiles(path).Where(f => f.IndexOf(contain.All(f.Contains), 0, StringComparison.CurrentCultureIgnoreCase) != -1).ToArray(); 
    return files; 
} 

Я пытаюсь получить список файлов, которые соответствуют критериям, и мне удалось получить правильный список, но только для чувствительных маркеров.

(В воздаем вы можете увидеть мои попытки получить для случая нечувствительный, но есть ошибка ...)

Как я могу проверить, если имя файла содержит всю строку в списке в случае нечувствительным?

EDIT, пример:

Допустим, у меня есть последующие файлы в моем каталоге:

proj_debug_3.2.0.txt

proj_release_3.2.1.txt

proj_release_3.2.1_useThis_TRY.txt

Про j_release_3.2.1_UseThis.txt

так, чтобы позвонить в

enumerateFilesByFilter(path, new List<String> { "Release", "useThis" }, new List<String> {"try", "debug" }); 

должен возвращать proj_release_3.2.1_UseThis.txt файлу

Спасибо!

+2

Fyi, используйте 'Directory.EnumerateFiles' вместо' Directory.GetFiles', если вы используете 'Where', так как он может начать обработку до того, как будут возвращены все файлы, а не GetFiles, который сначала создает массив всех файлов. –

+0

Может ли файл быть как содержащимся, так и не содержать одновременно? –

+0

@ ЮвалИцчаков, №. содержать список отличается от notContain ... – AsfK

ответ

1

В первом, я бы определить новый метод расширения для регистронезависимого поиска:

public static class StringExtensions 
{ 
    public static bool Contains(this string source, string pattern, StringComparison comparision) 
    { 
     return source.IndexOf(pattern, comparision) >= 0; 
    } 
} 

Затем переписать метод так:

public static IEnumerable<string> EnumerateFilesByFilter(String path, List<String> include, List<String> exclude) 
    { 
     return Directory.EnumerateFiles(path). 
      Where(f => include.All(i => f.Contains(i, StringComparison.OrdinalIgnoreCase))). 
      Where(f => exclude.All(i => !f.Contains(i, StringComparison.OrdinalIgnoreCase))); 
    } 

Пожалуйста, обратите внимание, что я использовал в качестве IEnumerable return type и Directory.EnumerateFiles() для перечисления файловой системы. Таким образом, вся операция намного эффективнее и использует только перечисления.

+0

спасибо, но у вас есть ошибка на 'f => include.All' line – AsfK

+0

Что вы подразумеваете под« у вас есть error "? Я попробовал это с вашим примером выше, он компилирует и дает правильный результат. –

+0

Вы правы, я помещаю класс' StringExtensions' в неположенное место. Большое вам спасибо! – AsfK

1

Это должно работать по желанию:

private String[] enumerateFilesByFilter(String path, List<String> contain, List<String> notContain) 
{ 
    String[] files = Directory.EnumerateFiles(path) 
     .Where(f => contain.All(s => s.IndexOf(f, StringComparison.CurrentCultureIgnoreCase) >= 0) 
      && !notContain.Any(s => s.IndexOf(f, StringComparison.CurrentCultureIgnoreCase) >= 0)) 
     .ToArray(); 
    return files; 
} 

Обратите внимание, что я использую Directory.EnumerateFiles вместо Directory.GetFiles, потому что он может начать обработку, прежде чем все файлы будут возвращены в отличие от GetFiles, который первым создает массив всех файлов.

Возможно, вам стоит также рассмотреть возможность использования System.IO.Path.GetFileName(f) для проверки только имени файла вместо полного пути.

+0

спасибо за ответ, но я получил пустой массив ... (и этого не происходит, когда я использую свою команду 'String [] files = Directory.GetFiles (path) .Where (f => (содержать.All (f.Contains)) && (! notContain.Any (f.Contains))) ToArray(); ' – AsfK

+0

@AsfK: возможно, потому что' notContain.Any' теперь работает нечувствительным к регистру и который фильтрует больше, чем раньше. Трудно помочь без выборочных данных, которые дезориентируют проблему. –

0

Наконец я нашел решение (решение некрасиво, но работает):

private String[] enumerateFilesByFilter(String path, List<String> contain, List<String> notContain) 
{ 
    String[] files = Directory.EnumerateFiles(path).Where(f => (contain.All(c => f.ToLower().Contains(c.ToLower()))) && 
     (!notContain.Any(c => f.ToLower().Contains(c.ToLower())))).ToArray(); 
    return files; 
} 
Смежные вопросы