Entwickler-Ecke

Basistechnologien - Sortieren einer Liste nach Sortierkriterien anderer Liste


alegria - Do 15.10.09 08:57
Titel: Sortieren einer Liste nach Sortierkriterien anderer Liste
Also ich hoffe sehr Ihr könnt mir helfen. Ich möchte einfach die Liste cities entsprechend der Reihenfolge von bigcities sortieren. Wie gehts das? Hilft hier LINQ?

Kleines Codebeispiel:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public List<string> cities = new List<string>();
        public List<string> bigcities = new List<string>();

        private void button1_Click(object sender, EventArgs e)
        {
            // ???
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cities.Add("Paris");
            cities.Add("Frankfurt");
            cities.Add("Lyon");
            cities.Add("Córdoba");
            cities.Add("Moskau");
            cities.Add("Mexico Ciudad");

            bigcities.Add("Mexico Ciudad");
            bigcities.Add("New York");
            bigcities.Add("Paris");            
        }
    }


Rauskommen sollte das hier:
Mexico Ciudad
Paris
Frankfurt
Lyon
Córdoba
Moskau

Vielen Dank im Voraus für Eure Hilfe!


Christian S. - Fr 16.10.09 17:42

Hallo!

Eine eher unperformante Lösung dürfte sowas hier sein (ich hab's in Delphi Prism geschrieben, aber die Umsetzung in C# sollte nicht so schwer sein):


Delphi-Prism-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
  var citiesBak := new List<String>(cities); //Backup von der Liste machen, damit man die alte Sortierung kennt.

  cities.Sort(method(x, y : String) : Integer; //ein Comparison<String> als Parameter
    begin
      if x = y then //gleicher String -> 0
        exit 0;

      if bigcities.Contains(x) and (not bigcities.Contains(y)) then //x in BigCities, aber y nicht
        exit -1;

      if bigcities.Contains(y) and (not bigcities.Contains(x)) then //y in BigCities, aber x nicht
        exit 1;

      if not (bigcities.Contains(x) or bigcities.Contains(y)) then //keines von beidem in BigCities -> alte Sortering erhalten
        exit iif(citiesBak.IndexOf(x) > citiesBak.IndexOf(y), 1, -1);

      exit iif(bigcities.IndexOf(x) > bigcities.IndexOf(y), 1, -1); //beide in BigCities, Sortierung von dort nehmen
    end);


Zwei "Übersetzungshilfen":
(1) Der Parameter, den ich der Sort-Methode übergebe, ist eine anonyme Methode. Wenn Du damit man Google fütterst, solltest Du schnell finden, wie man das in C# macht
(2) "iif" ist sowas wie der ternäre Operator in C#. iif(a > b, 12) wäre in C# also a > b ? 1 : 2

Grüße
Christian


Kha - So 18.10.09 23:03

Christian, erst dein Code hat mir klar gemacht, was überhaupt (hoffentlich?) gefordert ist :lol: . In O(m+n) geht es so:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
    static IEnumerable<T> Order<T>(IList<T> list, IList<T> by)
    {
      var listSet = new HashSet<T>(list);
      var bySet = new HashSet<T>(by);

      return
        by.Where(listSet.Contains)
        .Concat(listSet.Where(x => !bySet.Contains(x)));
    }


alegria - Mo 19.10.09 08:08

Danke! Hat funktioniert... :)