2017-01-05 6 views
0

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

перед записью в файл из списка

List<string> List = new List<string>(); 

я использую отчетливым, чтобы избежать дубликатов:

IEnumerable<string> sepStr = List.Distinct(); 

foreach (string StrExtractToFile in sepStr) 
{      
    using (StreamWriter sw = File.AppendText(doc.txt)) 
      sw.WriteLine(StrExtractToFile); 
} 

, но я хочу избежать всех дубликатов, кроме слова «граница». в файл, если он существует в списке, «граница». должны быть переданы в файл с дубликатами, следует избегать других дубликатов.

Я не уверен, что правильно или правильно сказать лучший способ сделать это. Я не уверен, что если String.Contains Method путь для такого случая

+0

делает заказ вопрос? – taquion

+0

@taquion Привет, да, порядок важен. список обновляется все время, но заказ должен быть сохранен. и я пишу строку по строке из списка в файл и так же, как из файла в список. – nikorio

ответ

2

Вы можете сделать свой обычай IEqualityComparer<>, чтобы получить желаемое поведение:

class CustomComparer : EqualityComparer<string> 
{ 
    public override bool Equals(string x, string y) 
    { 
     if (x == "border" || y == "border") return false; 
     return Default.Equals(x, y); 
    } 

    public override int GetHashCode(string obj) 
    { 
     return obj.GetHashCode(); 
    } 
} 

Затем вызовите Distinct перегрузку проходящих экземпляр компаратора:

SplitContList.Distinct(new CustomComparer()); 

В качестве альтернативы, вы можете сделать что-то вроде этого:

SplitContList.Select((w, i) => new { w, key = w == "border" ? i : 0 }) 
      .Distinct() 
      .Select(x => x.w); 
+0

Я пробовал в обоих направлениях, но он удаляет границу для записи в файл, не уверен, может быть, я делаю что-то неправильно. Я отредактировал мой вопрос, чтобы быть более ясным – nikorio

+0

@nikorio: так что вы хотите, чтобы дубликаты не появлялись вообще? если список «a», «border», «a», «b», «c», «border», «c», «d» должен быть результирующим списком? –

0

Вы можете быть в состоянии сделать это с помощью Linq, но я просто хотел бы использовать быстрый цикл ...

List<String> Str = new List<String>(); 
foreach (string s in SplitContList) 
{ 
    if (s == "Border" || !Str.Contains(s)) 
     Str.Add(s); 
} 

Это добавить строку в список если это «Граница» или если он еще не включен в список.

+0

HI, у меня есть вопрос редактирования, потому что он недостаточно ясен, и ничего из заданных кодов не работает для меня – nikorio

+0

Этот цикл просто отфильтровывает повторяющиеся строки. Вы можете сделать свой stringwriter.append (или что-нибудь еще, что вы хотите сделать) одновременно с вызовом Str.Add (s) ;. –

0
void Main() 
{ 
    var items = new List<String>{"Brett", "James", "James", "Border", "Border", "John"}; 
    var distincts = items.Where(x => x != "Border").Distinct().ToList(); 
    var borders = items.Where(x => x == "Border").ToList(); 
    distincts.Concat(borders).ToList().ForEach(x => Console.WriteLine(x)); 
} 
+0

Привет, тот же результат, что и с другим решением, я редактирую свой вопрос, так что, возможно, это было неясно, проверьте мое редактирование – nikorio

+0

Вы говорите: «но я хочу избежать всех дубликатов, кроме слова« граница ». в файл, если он существует в списке, «граница». должны быть переданы в файл с дубликатами, следует избегать других дубликатов ». Вот что это делает. Он удаляет дубликаты, за исключением случаев, когда они являются границей слов в макете.Я не знаю, чего вы действительно хотите, если не предоставите более подробную информацию. – djangojazz

0

Может быть, есть элегантный LINQ-решения я не думал, но классическое решение не так уж трудно думать о любом

List<string> results = new List<string>(); 
foreach(var s in SplitContList) 
{ 
    if(!results.Contains(s) || s == "border.") 
    { 
     results.Add(s); 
    } 
} 
+0

@ Paul Kertscher Привет, я редактировал свой вопрос, кажется, что это было не совсем понятно, потому что ничто из заданных решений не работает для меня надлежащим образом. – nikorio

0

Я иду за @Elemental Пита ответ только с одним изменить

var SplitContList = new List<string>(); 
     var Str = new List<String>(); 
     foreach (var s in SplitContList) 
      if (s.Equals("border",StringComparison.InvariantCultureIgnoreCase)|| !Str.Contains(s)) 
       Str.Add(s); 

Только в случае, если не имеет значения, дело

+0

@djangojazz отвечает тоже, но он перечисляет дважды список, пока этот (Elemental Pete's) Ответ только один раз – taquion

+0

Привет, я редактировал свой вопрос, потому что это было непонятно, так что кажется, что ничего не работает, как мне нужно, или я делаю что-то не так, просто отметьте – nikorio

0
var filteredList = SplitContList 
         .Where(c => c != "border") 
         .GroupBy(v => v) 
         .Select(group => group.First()) 
         .Concat(SplitContList.Where(c => c == "border")).ToList(); 
+0

. Я редактирую вопрос, потому что кажется, что это было не ясно. Не уверен, но ничего не работает из данных решений. Правильная форма. – nikorio

+0

@nikorio Если решение не работает downvote, пожалуйста. – wp78de

+0

вы можете попытаться описать более подробно. – aircraft

0

Я бы пошел с другой коллекцией, содержащей уже прикрепленные строки и проверьте петлю.

List<string> List = new List<string>(); 
HashSet<string> alreadyUsed = new HashSet<string>(); 
using (StreamWriter sw = File.AppendText(doc.txt)) 
{ 
    foreach (string StrExtractToFile in List) 
    { 
     if (StrExtractToFile == "border" || !alreadyUsed.Contains(StrExtractToFile)) 
     { 
      alreadyUsed.Add(StrExtractToFile); 
      sw.WriteLine(StrExtractToFile); 
     } 
    } 
}