J'ai besoin d'un exemple de base pour utiliser l'interface IComparable
afin de pouvoir trier par ordre croissant ou décroissant et par différents champs du type d'objet que je trie.Comment utiliser l'interface IComparable?
Répondre
Eh bien, puisque vous utilisez List<T>
il serait beaucoup plus simple d'utiliser un Comparison<T>
, par exemple:
List<Foo> data = ...
// sort by name descending
data.Sort((x,y) => -x.Name.CompareTo(y.Name));
Bien sûr, avec LINQ vous pouvez simplement utiliser:
var ordered = data.OrderByDescending(x=>x.Name);
Mais vous pouvez ré-introduire dans d'List<T>
(pour en place réordonnancement) assez facilement; Voici un exemple qui permet Sort
sur List<T>
avec la syntaxe lambda:
using System;
using System.Collections.Generic;
class Foo { // formatted for vertical space
public string Bar{get;set;}
}
static class Program {
static void Main() {
List<Foo> data = new List<Foo> {
new Foo {Bar = "abc"}, new Foo {Bar = "jkl"},
new Foo {Bar = "def"}, new Foo {Bar = "ghi"}
};
data.SortDescending(x => x.Bar);
foreach (var row in data) {
Console.WriteLine(row.Bar);
}
}
static void Sort<TSource, TValue>(this List<TSource> source,
Func<TSource, TValue> selector) {
var comparer = Comparer<TValue>.Default;
source.Sort((x,y)=>comparer.Compare(selector(x),selector(y)));
}
static void SortDescending<TSource, TValue>(this List<TSource> source,
Func<TSource, TValue> selector) {
var comparer = Comparer<TValue>.Default;
source.Sort((x,y)=>comparer.Compare(selector(y),selector(x)));
}
}
Voici un exemple simple: «C'est super, mais si je veux être en mesure de contrôler l'ordre de tri, ou trier par un autre champ »
public class SortableItem : IComparable<SortableItem>
{
public int someNumber;
#region IComparable<SortableItem> Members
public int CompareTo(SortableItem other)
{
int ret = -1;
if (someNumber < other.someNumber)
ret = -1;
else if (someNumber > other.someNumber)
ret = 1;
else if (someNumber == other.someNumber)
ret = 0;
return ret;
}
#endregion
}
Simple. Tout ce que nous devons faire est d'ajouter quelques champs supplémentaires à l'objet. Nous allons d'abord ajouter une chaîne pour un type de tri différent, puis nous ajouterons un booléen pour indiquer si nous effectuons un tri par ordre décroissant ou croissant, puis ajouterons un champ qui détermine le champ que nous voulons rechercher.
public class SortableItem : IComparable<SortableItem>
{
public enum SortFieldType { SortNumber, SortString }
public int someNumber = -1;
public string someString = "";
public bool descending = true;
public SortFieldType sortField = SortableItem.SortFieldType.SortNumber;
#region IComparable<SortableItem> Members
public int CompareTo(SortableItem other)
{
int ret = -1;
if(sortField == SortableItem.SortFieldType.SortString)
{
// A lot of other objects implement IComparable as well.
// Take advantage of this.
ret = someString.CompareTo(other.someString);
}
else
{
if (someNumber < other.someNumber)
ret = -1;
else if (someNumber > other.someNumber)
ret = 1;
else if (someNumber == other.someNumber)
ret = 0;
}
// A quick way to switch sort order:
// -1 becomes 1, 1 becomes -1, 0 stays the same.
if(!descending) ret = ret * -1;
return ret;
}
#endregion
public override string ToString()
{
if(sortField == SortableItem.SortFieldType.SortString)
return someString;
else
return someNumber.ToString();
}
}
"Montrez-moi comment!"
Eh bien puisque vous avez demandé si bien.
static class Program
{
static void Main()
{
List<SortableItem> items = new List<SortableItem>();
SortableItem temp = new SortableItem();
temp.someString = "Hello";
temp.someNumber = 1;
items.Add(temp);
temp = new SortableItem();
temp.someString = "World";
temp.someNumber = 2;
items.Add(temp);
SortByString(items);
Output(items);
SortAscending(items);
Output(items);
SortByNumber(items);
Output(items);
SortDescending(items);
Output(items);
Console.ReadKey();
}
public static void SortDescending(List<SortableItem> items)
{
foreach (SortableItem item in items)
item.descending = true;
}
public static void SortAscending(List<SortableItem> items)
{
foreach (SortableItem item in items)
item.descending = false;
}
public static void SortByNumber(List<SortableItem> items)
{
foreach (SortableItem item in items)
item.sortField = SortableItem.SortFieldType.SortNumber;
}
public static void SortByString(List<SortableItem> items)
{
foreach (SortableItem item in items)
item.sortField = SortableItem.SortFieldType.SortString;
}
public static void Output(List<SortableItem> items)
{
items.Sort();
for (int i = 0; i < items.Count; i++)
Console.WriteLine("Item " + i + ": " + items[i].ToString());
}
}
qui est en fait assez yeucky, désolé de le dire. Il y a de bien meilleures approches, en particulier en utilisant LINQ ou une approche inspirée par LINQ ... –
Il n'y a rien qui dise que vous ne pouvez pas répondre à la question aussi si vous avez une meilleure idée. –
J'ai - je l'écris juste ;-p –
Si vous voulez genre dynamique, vous pouvez utiliser LINQ
var itemsOrderedByNumber = (from item in GetClasses() orderby item.Number select item).ToList();
var itemsOrderedByText = (from item in GetClasses() orderby item.Text select item).ToList();
var itemsOrderedByDate = (from item in GetClasses() orderby item.Date select item).ToList();
ou "Trier" méthode de la liste des classes:
List<Class1> itemsOrderedByNumber2 = new List<Class1>(GetClasses());
itemsOrderedByNumber2.Sort((a, b) => Comparer<int>.Default.Compare(a.Number, b.Number));
List<Class1> itemsOrderedByText2 = new List<Class1>(GetClasses());
itemsOrderedByText2.Sort((a, b) => Comparer<string>.Default.Compare(a.Text, b.Text));
List<Class1> itemsOrderedByDate2 = new List<Class1>(GetClasses());
itemsOrderedByDate2.Sort((a, b) => Comparer<DateTime>.Default.Compare(a.Date, b.Date));
Cela pourrait ne pas être en relation avec l'ordre de tri, mais il est encore - je pense - une utilisation intéressante de IComparable
:
public static void MustBeInRange<T>(this T x, T minimum, T maximum, string paramName)
where T : IComparable<T>
{
bool underMinimum = (x.CompareTo(minimum) < 0);
bool overMaximum = (x.CompareTo(maximum) > 0);
if (underMinimum || overMaximum)
{
string message = string.Format(
System.Globalization.CultureInfo.InvariantCulture,
"Value outside of [{0},{1}] not allowed/expected",
minimum, maximum
);
if (string.IsNullOrEmpty(paramName))
{
Exception noInner = null;
throw new ArgumentOutOfRangeException(message, noInner);
}
else
{
throw new ArgumentOutOfRangeException(paramName, x, message);
}
}
}
public static void MustBeInRange<T>(this T x, T minimum, T maximum)
where T : IComparable<T> { x.MustBeInRange(minimum, maximum, null); }
ces méthodes simples d'extension vous permettent d'effectuer la vérification de la plage de paramètres pour tout type qui implémente IComparable
comme ceci:
public void SomeMethod(int percentage, string file) {
percentage.MustBeInRange(0, 100, "percentage");
file.MustBeInRange("file000", "file999", "file");
// do something with percentage and file
// (caller will have gotten ArgumentOutOfRangeExceptions when applicable)
}
Pour être honnête, il est peu probable que vous l'utilisiez sur un type qui n'est pas 'IComparable
N'avait pas bien de cela. Merci pour le conseil. Cependant, cela ne montrerait-il pas tout à la méthode d'extension (= sur les types je serais "peu susceptible de l'utiliser sur") alors qu'avec la contrainte de type elle ne montrera que sur les types qui sont réellement IComparable? – peSHIr
using System;
using System.Collections.Generic;
using System.Text;
namespace Sorting_ComplexTypes
{
class Program
{
static void Main(string[] args)
{
Customer customer1 = new Customer {
ID = 101,
Name = "Mark",
Salary = 2400,
Type = "Retail Customers"
};
Customer customer2 = new Customer
{
ID = 102,
Name = "Brian",
Salary = 5000,
Type = "Retail Customers"
};
Customer customer3 = new Customer
{
ID = 103,
Name = "Steve",
Salary = 3400,
Type = "Retail Customers"
};
List<Customer> customer = new List<Customer>();
customer.Add(customer1);
customer.Add(customer2);
customer.Add(customer3);
Console.WriteLine("Before Sorting");
foreach(Customer c in customer)
{
Console.WriteLine(c.Name);
}
customer.Sort();
Console.WriteLine("After Sorting");
foreach(Customer c in customer)
{
Console.WriteLine(c.Name);
}
customer.Reverse();
Console.WriteLine("Reverse Sorting");
foreach (Customer c in customer)
{
Console.WriteLine(c.Name);
}
}
}
}
public class Customer : IComparable<Customer>
{
public int ID { get; set; }
public string Name { get; set; }
public int Salary { get; set; }
public string Type { get; set; }
public int CompareTo(Customer other)
{
return this.Name.CompareTo(other.Name);
}
}
Vous pouvez l'utiliser pour la liste de tri
namespace GenaricClass
{
class Employee :IComparable<Employee>
{
public string Name { get; set; }
public double Salary { get; set; }
public int CompareTo(Employee other)
{
if (this.Salary < other.Salary) return 1;
else if (this.Salary > other.Salary) return -1;
else return 0;
}
public static void Main()
{
List<Employee> empList = new List<Employee>()
{
new Employee{Name="a",Salary=140000},
new Employee{Name="b",Salary=120000},
new Employee{Name="c",Salary=160000},
new Employee{Name="d",Salary=10000}
};
empList.Sort();
foreach (Employee emp in empList)
{
System.Console.Write(emp.Salary +",");
}
System.Console.ReadKey();
}
}
}
- 1. Int32? avec IComparable
- 2. Problèmes avec tri et de IComparable
- 3. Conversion de tableau double en tableau IComparable
- 4. Comment puis-je m'assurer qu'un type de données implémente une interface IComparable?
- 5. Pourquoi la méthode <T> .Sort réorganiser égale IComparable <T> éléments?
- 6. Comparer.Compare a besoin d'un objet qui implémente IComparable mais jetteront exception sinon le premier paramètre est
- 7. Pourquoi IEnumerable <T> .Max ne peut-il pas être IComparable?
- 8. Comment: Utiliser MvcContrib.Pagination sans utiliser MvcContrib.Grid Voir
- 9. CIImage: Comment utiliser CIAffineTransform?
- 10. Comment utiliser IHTTPAsyncHandler?
- 11. Comment utiliser sprof?
- 12. JTidy Node.findBody() - Comment utiliser?
- 13. Comment utiliser les typelists
- 14. Comment utiliser Degrafa AutoShapes
- 15. Comment utiliser l'API rapidshare?
- 16. Comment utiliser YUI
- 17. Comment utiliser dataTable?
- 18. jQuery - comment utiliser stopPropagation()
- 19. Comment utiliser getActiveObject ("Excel.Application")
- 20. Comment utiliser RegEx?
- 21. Comment utiliser Window.OnClose
- 22. AT, RIL comment utiliser
- 23. Comment utiliser RewriteCond% N
- 24. Comment utiliser cronjob
- 25. Comment utiliser NTEventLogAppender?
- 26. Comment utiliser PerformanceCounterType AverageTimer32?
- 27. Comment utiliser DB2 Explain?
- 28. Comment utiliser Jquery contient?
- 29. Comment utiliser CWnd :: CreateEx
- 30. comment utiliser java stringtokenizer?
Votre réponse commence un peu confuse, il suppose que j'ai déjà lu des informations qui ne sont pas dans la question mais dans une réponse postée par l'OP. – Stijn