Sortowanie listy obiektów

0

Witam,
Muszę posortować listę obiektów. Do sortowania wykorzystuję metodę bąbelkową. Program się wysypuje na linijce

 ChairList.Reverse(i, i + 1);

wyświetlając komunikat:
Wartości przesunięcia i długości są spoza zakresu tablicy lub liczba przekracza liczbę elementów znajdujących się miedzy indeksem a końcem kolekcji źródłowej.
Jednak jak napiszę:

 temp = ChairList[i];
ChairList[i] = ChairList[i + 1];
ChairList[i + 1] = temp;

to wszystko działa.

kod:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SortAplication
{

    class Chair : IComparable<Chair>
    {
        public int chairLeg;
        public int chairArea;

        public int CompareTo(Chair ch)
        {
            return chairLeg.CompareTo(ch.chairLeg);
        }


        public Chair(int leg , int area ) {
            chairLeg = leg;
            chairArea = area;
        }

        ~Chair() { }       
    }


    class Program
    {
        static void Main(string[] args)
        {
            Random num = new Random();
            List<Chair> ChairList = new List<Chair>();

            for (int i = 0; i < 100; i++)
            {
                ChairList.Add(new Chair(num.Next(100), num.Next(100)));
                Console.WriteLine(ChairList[i].chairLeg + "\t" + ChairList[i].chairArea);
                
            }

            /*bubble sort*/
            int n = ChairList.Count;
            Console.WriteLine(n);
            do{
                for (int i = 0; i < n - 1; i++)
                {
                    if (ChairList[i].CompareTo(ChairList[i + 1]) > 0)
                    {
                        Chair temp = new Chair(0, 0);
                        temp = ChairList[i];
                        ChairList[i] = ChairList[i + 1];
                        ChairList[i + 1] = temp;
                        
                        //ChairList.Reverse(i, i + 1);  <-- TO NIE DZIAŁA 
                    }
                }
                n--;

            } while (n > 1);
            //************//

            Console.WriteLine("Posegregowana lista: ");
            for (int i = 0; i < 100; i++)
            {
                ChairList.Add(new Chair(num.Next(100), num.Next(100)));
                Console.WriteLine(ChairList[i].chairLeg + "\t" + ChairList[i].chairArea);

            }

            Console.ReadLine();


        }
    }
}

Jednocześnie chciałbym się zapytać o przydatność interfejsu IComparable Mam takie zalecenie aby go wykorzystać. Ale załóżmy, że teraz dodaję klasę Table i stoły także sortuję po ilości nóg. Jaką ja mam korzyść korzystania z interfejsu, skoro i tak musiałbym drugi raz zdefiniować metodę CompareTo(Table t) dla klasy Table.

1

Revers nie zamienia miejscami tylko odwaraca kolejność x elementów od jakiegoś indeksu czyli jak piszesz revers (99,100) to tak naprawdę każesz odwrócić kolejność wyszstkich elementów od pozycji 99 do 199, a że nie ma pozycji 199 to dostajesz wyjątek.
Nie używaj destruktora!.
Z icomparable chodzi o to żeby po pierwsze pokazać ze można porównywać elementy, to ważne bo nie jest oczywiste żeby krzesła porównywać po długości nóg ;) i w nie trywialnych przypadkach pozwala nie kopiować kodu, Gdyby Table dziedziczył po Table : Chair to nie musiał byś pisać osobnej metody compare, a nawet jeśli to jesli generyk był by taki sam to mógł byś porównywać stoły i krzesła w jednej kolekcji, np masz List<Icomparable<Chair> i trzymasz w niej liste krzeseł i stołow i możesz ją porównać.bez kombinowania jak koń pod góre.

0

Ok, a jeżeli chciałbym stworzyć 50 różnych klas i wszystkie ich obiekty sortować jedną metodą CompareTo(ComparableObj obj) , to jak do tego podejść?

0

Nie sortujesz ich metoda CompareTo tylko porównujesz. Możesz za to napisać jedną metodę Sort(ComparableObj obj) która posortuje dowolną ilość klas tak długo jak jak te klasy będą dziedziczyć po ComparableObj.
Jeśli chciałbyś jedną metodą sortować 50 klas możesz napisać klase implementującą IComparer lub IComparer<in T>. Jak sama nazwa wskazuje tak klasa służy do porównań. Możesz np. napisać comparer który będzie sortować meble po typie a potem drugi sortujący po typie i właściwościach mebla.

    class TypeComarer : IComparer
    {
        public int Compare(object x, object y)
        {
            if (x.GetType() == y.GetType())
                return 0;
            else if (x is Krzesło)
                return 1;
            else
                return -1;
        }
    }
    class MebleComarer : IComparer
    {
        private readonly TypeComarer typeComparer = new TypeComarer()
        public int Compare(object x, object y)
        {
            int result = typeComparer.Compare(x, y);
            if(result==0 && result is IComparable)
            {
                result = x.CompareTo(y);
            }
            return result;
        }
    }

Implementowanie IComparable sie przydało bo bo nie musisz wywoływać 50 róznych metod na porównanie tylko robisz to raz i sie nie przejmujesz co jest w środku.

Możesz po przetestować komparery np. tutaj list.OrderBy( mebel => mebel, Comparer).

0

Nie sortujesz ich metoda CompareTo tylko porównujesz. Możesz za to napisać jedną metodę Sort(ComparableObj obj) która posortuje dowolną ilość klas tak długo jak jak te klasy będą dziedziczyć po ComparableObj.

Ooo, to właśnie to chcę zrobić. Ale w takim razie nie wiem czy jest sens wykorzystywać interfejs tak jak to zrobiłem poniżej.

I zostaje jeszcze jedno pytanie. Jak mam różne klasy np:
class Chair : ComparableObj {}
class Table : ComparableObj {},
i chcę posortować dane w liście, to właśnie. Jak mam stworzyć listę róznych klas. Próbowałem zrobić coś takiego, ale lista jest zainicjowana samymi 0:

  class Chair : ComparableObj
    {
        public int chairLeg;
        public int chairArea;
        const String name = "Chair";


        public Chair(int leg , int area ) {
            chairLeg = leg;
            chairArea = area;
            comparable_var = area;
        }       
    }

    class Table : ComparableObj
    {
        public int tableLeg;
        public int tableArea;
        const String name = "Table";


        public Table(int leg, int area)
        {
            tableLeg = leg;
            tableArea = area;

            comparable_var = area;
            value1 = leg;
            value2 = area;
            name_obj = name;
            
        }
    }


    class ComparableObj : IComparable<ComparableObj>
    {
        public int comparable_var;
        public int value1;
        public int value2;
        public String name_obj;
        
        
        public int CompareTo(ComparableObj obj)
        {
            return comparable_var.CompareTo(obj.comparable_var);
        }
    }



    class Program
    {
        static void Main(string[] args)
        {
            Random num = new Random();
            List<ComparableObj> CommonList = new List<ComparableObj>();

            for (int i = 0; i < 100; i++)
            {
                CommonList.Add(new Chair(num.Next(100), num.Next(100)));
                Console.WriteLine(CommonList[i].value1 + "\t" + CommonList[i].value2);
            }

            /*bubble sort*/
             //...
            //************//
    }
}

0

Wszędzie masz zera ponieważ porównujesz po comparable_var której nie ustawiłeś, ustawiasz tylko pole i nogi w konstruktorze zero to domyślna wartość dla inta . Tak z innej beczki ale własnie przez takie problemy powinno się unikać publicznych zmiennych. Propeties sa lepsze bo pozwoliły by Ci synchronizować przy zmianie comparable_var i leg. Ale moim zdaniem lepiej spróbować czegoś w ten deseń.

    abstract class ComparableObj : IComparable<ComparableObj>
    {
         public virtual int Area {get; }
         public virtual int Leg {get; }

        public int CompareTo(ComparableObj obj)
        {
            return GetValueToCompare().CompareTo(obj.GetValueToCompare());
        }

        protected abstaract int GetValueToCompare();
    }

Tak na marginesie zamiast value1 CharArea i tableArea powinna być jedna zmienna.

1 użytkowników online, w tym zalogowanych: 0, gości: 1