2013-11-18 1 views
0

На самом деле, еще один заголовок для вопроса: Как найти персонажа с самым высоким алфавитным значением для текущей культуры?Закажите коллекцию французских строк и оставьте пустые записи в конце

Взгляните на следующий код:

static void Main(string[] args) 
{ 
    var input = new[] { "cote", "côte", "coté", "", "côté" }; 
    var maxString = new string(new[] { char.MaxValue }); 

    var byEnUsCulture = input.OrderBy(i => 
     (String.IsNullOrEmpty(i)) ? maxString : i, 
      StringComparer.Create(new CultureInfo("en-US"), false)).ToList(); 

    var byFrFrCulture = input.OrderBy(i => 
     (String.IsNullOrEmpty(i)) ? maxString : i, 
      StringComparer.Create(new CultureInfo("fr-FR"), false)).ToList(); 

    var byOrdinal = input.OrderBy(i => 
     (String.IsNullOrEmpty(i)) ? maxString : i, 
      StringComparer.Ordinal).ToList(); 

    foreach (var words in new[] { byEnUsCulture, byFrFrCulture, byOrdinal }) 
    { 
     foreach (var word in words) 
     { 
      Console.Write("{0} ", (string.IsNullOrEmpty(word)) ? "xxxx" : word); 
     } 
     Console.WriteLine(); 
    } 
} 

Выход вышеперечисленное:

xxxx cote coté côte côté 
xxxx cote côte coté côté 
cote coté côte côté xxxx 

Но то, что я пытаюсь получить это:

cote côte coté côté xxxx 

Можно ли заказывать вышеперечисленные слова с помощью информации культуры fr-FR и по-прежнему выводить пустой (заменяется на xxxx в выходных данных) в конце коллекции, все, что только с помощью OrderBy?

Примечание: Here - ссылка для предполагаемого заказа.

+0

Если вы знаете, что '«»' записи должны идти к концу, вы можете не только извлекать и объединить их после заказа с помощью 'TakeWhile (p => string.IsNullOrEmpty (p)'? – Gusdor

+0

'cote côte coté côté' Я как бы растерялся, как вы можете получить этот заказ ... если сортировка работает над символами слева направо, первые два указывают на то, что' ô> o', тогда как вторая и третья запись указывает, что 'ô oerkelens

+1

Действительно, я ничего не пропустил, спасибо за эту ссылку. (Я буду воздерживаться от каких-либо дальнейших замечаний о французском порядке сортировки ... но акцент акваланса? Ну, вы живете, вы учитесь :)) – oerkelens

ответ

4

Предполагаете, что вы можете создать свой собственный подкласс StringComparer, который всегда гарантирует, что пустые строки отсортированы последними, прежде чем отложить сравнение с FR-FR-компаратором.

+0

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

+0

@AlexFilipovici Вам нужна дополнительная функция без накладных расходов на обработку? Удачи с этим человеком! – Gusdor

+0

@AlexFilipovici Я реализовал это решение в своем ответе. Поскольку теперь он обрабатывает пустые строки как нулевые строки, на самом деле происходит меньше обработки. – Gusdor

0

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

  • Еле любой код
  • Работает с любой строки компаратором
  • Guarentees ваши пустые строки сортируются до конца
  • остается одной операции сортировки (почти уверен .net использует QSort)

пример кода:

class EmptyToEndComparer: StringComparer 
{ 
    public StringComparer InnerComparer { get; private set; } 

    public EmptyToEndComparer(StringComparer innerComparer) 
    { 
     if (innerComparer == null) throw new ArgumentNullException("innerComparer"); 
     InnerComparer = innerComparer; 
    } 
    public override int Compare(string x, string y) 
    { 
     //Invert the standard behavior on null or empty 
     //http://msdn.microsoft.com/en-us/library/x1ea0esc%28v=vs.110%29.aspx 

     if (string.IsNullOrEmpty(x) && !string.IsNullOrEmpty(y)) 
      return 1; 
     else if (!string.IsNullOrEmpty(x) && string.IsNullOrEmpty(y)) 
      return -1; 
     else 
      return InnerComparer.Compare(x, y); 
    } 

    public override bool Equals(string x, string y) 
    { 
     return x == y; 
    } 

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

Используйте класс как это:

var byEnUsCulture = input.OrderBy(i => i, new EmptyToEndComparer(StringComparer.Create(new CultureInfo("en-US"), false))).ToList(); 

var byFrFrCulture = input.OrderBy(i => i, new EmptyToEndComparer(StringComparer.Create(new CultureInfo("fr-FR"), false))).ToList(); 

var byOrdinal = input.OrderBy(i => i, new EmptyToEndComparer(StringComparer.Ordinal)).ToList(); 

Выход из моего теста:

cote coté côte côté xxxx 
cote côte coté côté xxxx 
cote coté côte côté xxxx