2010-04-28 4 views
4

У меня есть два файла, sourcecolumns.txt и destcolumns.txt. Мне нужно сравнить источник с dest и если dest не содержит исходное значение, напишите его в новый файл. Приведенный ниже код работает только у меня есть регистрозависимы вопросы, как это:C#, соответствующий двум текстовым файлам, с учетом регистра вопросов

источник: CPI
Dest: Cpi

Они не совпадают из-за Captial писем, так что я получаю неправильные выводы. Любая помощь всегда приветствуется!

string[] sourcelinestotal = 
    File.ReadAllLines("C:\\testdirectory\\" + "sourcecolumns.txt"); 
string[] destlinestotal = 
    File.ReadAllLines("C:\\testdirectory\\" + "destcolumns.txt"); 

foreach (string sline in sourcelinestotal) 
{ 
    if (destlinestotal.Contains(sline)) 
    { 
    } 
    else 
    { 
     File.AppendAllText("C:\\testdirectory\\" + "missingcolumns.txt", sline); 
    } 
} 

ответ

5

Вы можете сделать это, используя метод расширения для IEnumerable<string> как:

public static class EnumerableExtensions 
{ 
    public static bool Contains(this IEnumerable<string> source, string value, StringComparison comparison) 
    { 
     if (source == null) 
     { 
      return false; // nothing is a member of the empty set 
     } 
     return source.Any(s => string.Equals(s, value, comparison)); 
    } 
} 

затем изменить

if (destlinestotal.Contains(sline)) 

в

if (destlinestotal.Contains(sline, StringComparison.OrdinalIgnoreCase)) 

Однако, если множества большие и/или вы собираетесь делайте это очень часто, то, как вы это делаете, очень неэффективно. По существу, вы выполняете операцию O (n), а для каждой строки в источнике вы сравниваете ее с потенциально всеми линиями в пункте назначения. Было бы лучше создать HashSet из столбцов назначения с помощью case insenstivie-компаратора, а затем перебирать исходные столбцы, проверяя, существует ли каждый из них в HashSet столбцов назначения. Это был бы алгоритм O (n). обратите внимание, что Содержит на HashSet будет использовать компаратор, который вы предоставляете в конструкторе.

string[] sourcelinestotal = 
    File.ReadAllLines("C:\\testdirectory\\" + "sourcecolumns.txt"); 
HashSet<string> destlinestotal = 
       new HashSet<string>(
        File.ReadAllLines("C:\\testdirectory\\" + "destcolumns.txt"), 
        StringComparer.OrdinalIgnoreCase 
       ); 

foreach (string sline in sourcelinestotal) 
{ 
    if (!destlinestotal.Contains(sline)) 
    { 
     File.AppendAllText("C:\\testdirectory\\" + "missingcolumns.txt", sline); 
    } 
} 

В ретроспективе, я предпочитаю это решение более просто написать свой собственный нечувствительны к регистру содержит для IEnumerable<string>, если не нужен метод для чего-то еще. Фактически, для поддержки с использованием реализации HashSet на самом деле меньше кода (вашего собственного).

+0

@aba - в общем случае коллекция может содержать пустую строку, хотя, возможно, в этом случае нет. – tvanfosson

+0

Я не могу это скомпилировать Использование универсального типа 'System.Collections.Generic.HashSet 'требует аргументов типа' 0 '\t C – 2010-04-28 19:46:26

+0

Я упустил спецификатор типа в конструкторе HashSet. Я исправил это. – tvanfosson

0

Если вам не нужна чувствительность к регистру, преобразуйте свои строки в верхний регистр, используя string.ToUpper перед сравнением.

+5

Нет! Это не проходит * Turkey Test *. http://www.codinghorror.com/blog/2008/03/whats-wrong-with-turkey.html – dtb

+0

Очень неэффективно - гораздо лучше использовать флаги сравнения, как предлагают другие. –

4

Используйте метод расширения для ваших Содержит. Был найден блестящий пример here on stack overflow Код не мой, но я отправлю его ниже.

public static bool Contains(this string source, string toCheck, StringComparison comp) 
{ 
    return source.IndexOf(toCheck, comp) >= 0; 
} 

string title = "STRING"; 
bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase); 
+0

Это не решает проблему - он хочет проверить, содержит ли ** набор ** строк строки конкретной строки в режиме без учета регистра. Это проверяет только, если строка ** ** содержит другую строку без учета регистра. Вам нужно иметь метод расширения в 'IEnumerable ', а не 'string'. – tvanfosson

+0

Я видел ваш ответ, намного лучше, чем мой. Я честно не рассматривал аспект производительности, и я не знал о перегруженном конструкторе HashSet. Это всегда хорошее расширение, чтобы иметь в любом случае! – StyxRiver

 Смежные вопросы

  • Нет связанных вопросов^_^