Avatar billede lasserasch Juniormester
14. juni 2012 - 13:42 Der er 6 kommentarer

Random som altid giver samme resultat.

Hej alle.

Jeg står med følgende udfordring.


Jeg har nogle forskellige collections af objekter. Alle objekterne i samlingerne har et ID som er af typen GUID.

Jeg skal have genereret et Random nummer jeg kan sætte på alle objekterne i samlingen.

Men nummeret skal altid være ens for den enkelte liste, så længe dens indhold er konstant.



F.eks.:
Et stykke C# kode laver et udtræk over objekt type A fra en SQL database (f.eks. en nyhedsliste, ordreliste eller lign), og lægger objekterne i en generisk liste.

Alle objekterne i listen har så en property som hedder f.eks. "Tag".

Jeg skal nu have lavet en random måde at tildele "Tag" feltet en værdi.

Hvis der er 10 brugere som trække den samme liste, så skal min koden altid tildele samme værdi i "tag" feltet hver gang.

Men hvis listens indhold ændrer sig. F.eks. hvis der kommer 2 nyheder mere i listen eller nogle af nyhederne er skiftet ud, så skal det igen være en ny random som kan tildele helt andre værdier til "tag" feltet.

Så jeg tænker at jeg skal bruge både antallet i listen samt ID'erne i listen når værdierne for "Tag" feltet skal kalkuleres.

Mulige værdier skal være i "tag" feltet skal være 0 - 4.


Hvordan ville i gribe sådan en opgave an?

Mvh.
Lasse
Avatar billede Syska Mester
14. juni 2012 - 14:43 #1
Kig på GetHashCode og Equals på objectet.

eks:


    public class Person
    {
        public IList<Person> Persons { get; set; }

        public string Name { get; set; }
        public int Age { get; set; }


        public bool Equals(Person other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.Persons, Persons) && Equals(other.Name, Name) && other.Age == Age;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (Person)) return false;
            return Equals((Person) obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int result = (Persons != null ? Persons.GetHashCode() : 0);
                result = (result*397) ^ (Name != null ? Name.GetHashCode() : 0);
                result = (result*397) ^ Age;
                return result;
            }
        }
    }
Avatar billede Syska Mester
14. juni 2012 - 14:52 #2
Der er vist nogen fejl mht sammenligning af "Persons" listen, men du bør i hvert fald kigge på GetHashCode().

mvh
Avatar billede arne_v Ekspert
15. juni 2012 - 17:42 #3
Hvis der skal vaere garanti for ny vaerdi ved aending, saa er man noedt til at konkatanere alle vaerdier.

Hvis man kan leve en en mikroskopisk risiko for at en aendring ikke giver en ny vaerdi, saa kan man bruge hash.

Men grundliggende lyder designet forkert + det kan simpelthen ikke passe at naar man tilfoejer/fjerner et objekt i listen saa skal alle objekter aendres.

Kan du ikke have et back link fra objektet til listen og saa have en version/konkat/hash i den? (kraever naturligvis at List<> wrappes i en custom klasse, men det er ganske paent OO)
Avatar billede kalatt Nybegynder
15. juni 2012 - 19:14 #4
Du kunne lave en hash over uddrag af alle objekterne og så bruge denne værdi til seed'e Random med.
Avatar billede lasserasch Juniormester
15. juni 2012 - 23:08 #5
Arne -> Jeg kan sagtens leve med den mikroskopiske chance for at det ikke giver en ny værdi. Det er noget som skal bruge i en web sammenhæng til at lægge nogle css klasser på nogle elementer i nogle lister.

Men den helt nøjagtige, hvorfor osv, er bare en så lang historie og lidt for indviklet til at forklare her i dette forum. Så jo designet er god nok når man kender hele baggrunden for det. Men jeg kan godt forstå det lyder lidt mærkeligt, når man ikke gør.

Kalatt -> Ville du så lægge alle ID'erne for alle elementer i listen sammen som en string og bruges denne strings Hash værdi eller skal det gøres på en anden måde.


Nedenstående kode ser udmiddelbart ud til at virke fint for mig. Men kan i se noget galt i den, eller er det en OK løsning?


Tak for indput til jer alle....


private void SetTagValues()
        {
            List<item> items = new List<item>();
            items.Add(new item() { ID = Guid.Parse("d150df1b-01ba-45b7-aeb1-4ca5c2f20a64"), Name = "Item 1" });
            items.Add(new item() { ID = Guid.Parse("9aa8e334-49e7-4a30-b06b-9a3c31795385"), Name = "Item 2" });
            items.Add(new item() { ID = Guid.Parse("00373f71-5d08-4e9a-840f-9bb3c8193518"), Name = "Item 3" });
         
            StringBuilder sb = new StringBuilder();
            foreach (item i in items)
            {
                sb.Append(i.ID.ToString());
            }
            int hash = sb.ToString().GetHashCode();
           
            Random r = new Random(hash);
            foreach (item i in items)
            {
                i.Tag = r.Next(1, 4);
            }
        }
    }


    public class item
    {
        public Guid ID { get; set; }
        public string Name { get; set; }
        public int Tag { get; set; }
    }



Mvh.
Lasse
Avatar billede arne_v Ekspert
16. juni 2012 - 03:24 #6
Det er ikke umiddelbart indlysende hvor 1 og 4 kommer fra.

Og du skal vaere klar over at forskellig raekkefoelge betyder forskellig hash

Men ellers ser det OK ud.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester