2010-12-06 6 views
2

Je travaille sur un filtrage personnalisé et un tri d'un ensemble de données, basé sur une collection de champs de tri envoyés depuis le navigateur client, et j'utilise Dynamic Linq pour obtenir (la plupart) de l'effet désiré. Je rencontre un problème lorsque j'essaie de trier par une colonne de type String, qui contient à la fois des chaînes traditionnelles et des nombres stockés sous forme de chaînes. Il ne semble pas que je puisse transmettre une valeur d'énumération StringComparison ou spécifier un paramètre IComparer pour la fonction Linq orderby.Linq dynamique: comment spécifier le type StringComparison?

Mon code de tri ressemble:

myList.AsQueryable().OrderBy("StringColWithNums ASC") 

je me retrouve avec:

1 
10 
100 
11 
12 
2 
20 

au lieu de:

1 
2 
10 
11 
12 
20 
100 

Toute personne qui a une expérience de faire quelque chose de semblable?

Répondre

0

Il semble que ce n'est pas quelque chose qui peut être accompli avec Dynamic Linq, du moins pas dans .NET 2.0/3.5. J'ai fini par modifier le code source de Dynamic Linq afin d'accomplir ce dont j'avais besoin.

1
myList.AsQueryable().Sort((r, s) => int.Parse(r).CompareTo(int.Parse(s))); 

prendra quelques ajustements si ce sont des objets, il suffit d'utiliser int.Parse(r.StringColWithNums), ou quel que soit le champ est.

Oops, désolé, n'a pas lu toutes les OP pour le voir a des lettres aussi, et vous voulez que la dynamique LINQ, édition

EDIT

Je ne sais pas que vous allez être capable de le faire en utilisant Dynamic linq et en passant IComparer. Vous pourrez peut-être le faire après avoir obtenu les résultats (c'est-à-dire, comme je l'ai écrit à l'origine, avec des modifications). Commentez si vous voulez poursuivre cette ligne.

0

Il s'agit d'un problème fondamental pour tenter d'effectuer des comparaisons numériques dans une comparaison de chaînes. Deux façons je faire:

  • Lors du chargement de la liste, les numéros de préfixe avec une quantité de zéros qui accompagnera la taille de la chaîne max, à savoir String.Format("000000", number). Cela ne fonctionnera que si vous vous souciez surtout du tri et moins de l'apparence des résultats - même alors, vous pouvez convertir "000010" en numérique et appeler la méthode ToString() pour afficher à nouveau le numéro sans les zéros en tête.

  • Écrivez votre propre implémentation (méthode d'extension) de OrderBy dans laquelle vous passez une fonction (ou fonction anonyme) en tant que paramètre pour trier à nouveau les résultats appelant la méthode transmise.

0

Vous pouvez résoudre en écrivant un nouveau comparateur chaîne

class AlphaNumericComparer : IComparer<string> 
     { 
      public int Compare(string x, string y) 
      { 
       // if both values are integers then do int comparision 
       int xValue, yValue; 
       if (int.TryParse(x, out xValue) && int.TryParse(y, out yValue)) 
        return xValue.CompareTo(yValue); 

       return x.CompareTo(y); // else do string comparison 
      } 
     } 

Ensuite, vous pouvez utiliser le comparateur dans les méthodes comme OrderBy et Trier

var sorted = lst.OrderBy(s => s, new AlphaNumericComparer()); 

lst.Sort(new AlphaNumericComparer()); 

Cela vous donnera le résultat souhaité. Si ce n'est pas le cas, modifiez simplement le comparateur.

+0

Je ne pense pas que vous pouvez utiliser une ficelle de chaîne avec linq dynamique cependant, je suis descendu cette route et n'ai pas pu l'obtenir pour aller. – BlackICE

Questions connexes