Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[.NET Linq] Recursive query op objecten

Pagina: 1
Acties:

  • KoW
  • Registratie: Juli 2001
  • Laatst online: 17-08-2022

KoW

Parse parsed te veel

Topicstarter
Met linq heb ik een collectie van objecten gemaakt (curTeams)

Nu wil ik die teams in wedstrijden indelen op een dusdanige manier dat elk team eenmaal tegen elk van de andere teams speelt.
Daarvoor heb ik deze query bedacht:
C#:
1
2
3
4
5
6
IEnumerable<Game> curGames =
from s1 in curTeams
from s2 in curTeams
where s2.ID > s1.ID
orderby s1.ID, s2.ID
select new Game(s1, s2);

Game is een class die (in dit geval) 2 team objecten meekrijgt die uiteindelijk als properties van het game object gaan gelden.

Qua resultaat geeft dit precies wat ik zoek, alleen, het lijkt wel alsof er iets vreemds gebeurd met s2 serie.
Het lijkt wel alsof de team objecten daar opnieuw worden aangemaakt. (gekopieerd) De team objecten uit de s1 serie blijven wel gelijk.

Wat ik wil is om vanuit het team object te kunnen kijken naar de bijbehorende game objecten. Daarvoor registreer ik (in de initialisatie van het game object) het game object bij het teamobject.
C#:
1
2
3
4
TeamA = newTeamA;
TeamA.Attachgame(this);
TeamB = newTeamB;
TeamB.Attachgame(this);

Dat werkt perfect voor de s1 serie (zie query), maar niet voor de s2 serie. Om te controleren of het misschien iets te maken had met teamA en teamB heb ik zowel Game(s1, s2) als Game(s2, s1) geprobeerd in de creatie-query.

Voor elk "s1" team kan ik nu de "s1" wedstrijden terug vinden, maar niet de "s2" wedstrijden.
Voor elk "s2" team kan ik alleen de huidige wedstrijd zien.

Voorbeeld:
code:
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
30
teams: A, B, C, D
games:
0: A - B
1: A - C
2: A - D
3: B - C
4: B - D
5: C - D

Nu zou je verwachten dat als je per team gaat kijken dat je krijgt:
A: 0, 1, 2
B: 0, 3, 4
C: 1, 3, 5
D: 2, 4, 5

In werkelijkheid krijg ik:
"s1" teams
Game0 A: 0, 1, 2
Game1 A: 0, 1, 2
Game2 A: 0, 1, 2
Game3 B: 3, 4 (geen 0 als "s2" team)
Game4 B: 3, 4 (geen 0 als "s2" team)
Game5 C: 5 (geen 1, 3 als "s2" team)
"s2" teams
Game0 B: 0
Game1 C: 1
Game2 D: 2
Game3 C: 3
Game4 D: 4
Game5 D: 5

Wat doe ik nu fout :?
Het principe werkt op zich, anders zou het bij de "s1" teams ook niet werken. Doet Linq soms iets raars wanneer je een select doet op 2x dezelfde data ?
Het is ook niet dat "s2" in zijn geheel een kopie is van de teams. In dat geval zou ik voor teamC en teamD uit de "s2" teams in ieder geval resp. 1, 3 en 2, 4, 5 moeten zien.

  • mindcrash
  • Registratie: April 2002
  • Laatst online: 22-11-2019

mindcrash

Rebellious Monkey

Ten eerste: Hongarische notatie leest niet echt lekker in .NET code en is eigenlijk ook niet echt nodig. Teams en Games leest een stuk lekkerder dan curTeams en curGames ;)

Ten tweede: ik denk dat je probleem in de where clause zit. Je doet een vergelijking "groter dan", terwijl ik denk dat je misschien eigenlijk op zoek bent naar "ongelijk aan". :)

"The people who are crazy enough to think they could change the world, are the ones who do." -- Steve Jobs (1955-2011) , Aaron Swartz (1986-2013)


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 16-11 18:33
mindcrash schreef op woensdag 30 januari 2008 @ 22:40:
Ten eerste: Hongarische notatie leest niet echt lekker in .NET code en is eigenlijk ook niet echt nodig. Teams en Games leest een stuk lekkerder dan curTeams en curGames ;)
Waar zie jij die dan? :?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • KoW
  • Registratie: Juli 2001
  • Laatst online: 17-08-2022

KoW

Parse parsed te veel

Topicstarter
offtopic:
[quote]mindcrash schreef op woensdag 30 januari 2008 @ 22:40:
Ten eerste: Hongarische notatie leest niet echt lekker in .NET code en is eigenlijk ook niet echt nodig. Teams en Games leest een stuk lekkerder dan curTeams en curGames ;)
[/quote]
Games gebruik ik al in de verdere code. Dit is namelijk een subquery. Maar zo moeilijk leest die 3x dat het in bovenstaande code voorkomt toch niet ;)
Ten tweede: ik denk dat je probleem in de where clause zit. Je doet een vergelijking "groter dan", terwijl ik denk dat je misschien eigenlijk op zoek bent naar "ongelijk aan". :)
In het voorbeeld (daar is de camelCase notatie er uit gehaald :) ) is te zien dat het games resultaat wel klopt. Alleen worden er voor "s2" kopieen van de losse team objecten gebruikt ipv het origineel. Dat is het probleem waar ik tegen aan loop.

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
Eerste codeblok, eerste regel ;)

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Ik denk dat het komt omdat je een object twee keer aan een game toevoegt: een keer als S1 en een keer als S2. Jij wilt juist dat je het object dat je als s2 doorgeeft aan Game een NIEUWE instance is (denk ik, ik vind de probleemomschrijving vaag). Linq to objects maakt geen copieen aan van objects, alleen in projections worden nieuwe objects gemaakt.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • KoW
  • Registratie: Juli 2001
  • Laatst online: 17-08-2022

KoW

Parse parsed te veel

Topicstarter
Ja, maar het zijn wel 2 verschillende objecten.
Versimpeld komt de query neer op:
SQL:
1
2
3
4
teams = A, B, C, D, E
Select s1, s2
from teams AS s1, teams AS s2
where s1 > s2

Het resultaat daarvan staat op regel 3-8 in codeblok 3.

Nu doe ik diezelfde query, maar dan met objecten.
Aangezien een object referentietype is wordt er dus gewerkt met een collectie van referenties, en dat 2x.
Bij het aanroepen van new Game(s1, s2) maak je dus een nieuw Game object aan met als parameters 2 referenties naar 2 verschillende Team objecten.

Nu blijkt dat de eerste (s1) netjes een referentie is naar een teamobject uit de teams collectie. Dat is precies zoals verwacht.
Normaal zou je denken dat de tweede (s2) ook een referentie is naar een ander teamobject uit diezelfde teams collectie. In werkelijkheid is het een referentie naar een kopie van het oorspronkelijke teamobject.
Dat (dat het een kopie is ipv het origineel) is het probleem.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Is team een struct of een class? Want dat is denk ik wat er aan de hand is. Ik snap 1 2 3 niet hoe hij een copie kan maken van een object zonder clone features, maar een struct is een value type en wordt wel gecopieerd.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • KoW
  • Registratie: Juli 2001
  • Laatst online: 17-08-2022

KoW

Parse parsed te veel

Topicstarter
Met objecten bedoel ik inderdaad een class, en daarmee ook een referentietype.
Met de s1 team serie doet hij het wel, met de s2 serie, die uiteindelijk dezelfde collectie referenties bevat doet hij het niet :?

  • apokalypse
  • Registratie: Augustus 2004
  • Laatst online: 00:50
0: A - B
1: A - C
2: A - D
3: B - C
4: B - D
5: C - D
Het lijkt erop dat hij alleen de eerste kolom pakt? DUs niks referenties probleem, maar de (LINQ) query.

  • KoW
  • Registratie: Juli 2001
  • Laatst online: 17-08-2022

KoW

Parse parsed te veel

Topicstarter
Hoe bedoel je :? Het resultaat klopt gewoon (SQL), alleen is team B in game0 een ander team B dan die van game3 en game4.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Jouw query is in-memory, dus heeft niets met sql te maken. Hij zal met een enumerator de lijst aflopen en per from dat dus doen, dus hoe er copys gemaakt worden is mij een raadsel, want waarom zou hij dat doen? Weet je zeker dat het clones zijn? Heb je dat gechecked met een Hashset?

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • KoW
  • Registratie: Juli 2001
  • Laatst online: 17-08-2022

KoW

Parse parsed te veel

Topicstarter
ik heb het gechecked met een query voorwaarde teamA == testTeam || teamB == testTeam
Wat een hashset is zoek ik vanmiddag uit na werktijd.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
KoW schreef op vrijdag 01 februari 2008 @ 08:26:
ik heb het gechecked met een query voorwaarde teamA == testTeam || teamB == testTeam
Wat een hashset is zoek ik vanmiddag uit na werktijd.
Die test is niet correct, dat kan nl. ook een bug van jouw kant zijn.

Je moet alle objects (dus s1 en s2) in een hashset of dictionary stoppen en eerst checken of ze er al in zitten. Bij copies is dat dus niet zo, bij dezelfde objects is dat dus wel zo. Als na afloop je 2 keer zoveel objects hebt in je hashset als waar je mee begon, dan worden er objects gecopieerd, anders heb jij ergens een foutje in je code ;)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • pedorus
  • Registratie: Januari 2008
  • Niet online
Geinig voorbeeld. Het gekke is dat ik dit niet kan reproduceren.
Wat me wel opvalt is dat dit natuurlijk fout gaat als je curGames twee keer doorloopt. Je maakt dan twee keer zoveel Games aan. Deze blijven bestaan doordat ze aan de Teams gaan hangen vanwege de attachGame in de constructor. Dit kan je oplossen door .ToList() te gebruiken.

En ik vraag me nog af waarom je niet
C#:
1
this.Team1 = Team2;

doet. Of zelfs:
C#:
1
select new Game { Team1 = s1, Team2 = s2 }

En dan de attachGames in een for-each doet, of bij de property set.

Waarschijnlijk ligt het aan hoe curTeams wordt gemaakt. Test het anders eens zo:
C#:
1
2
3
List<Team> curTeams = 
    ( from i in Enumerable.Range('A', 4)
      select new Team { ID = (char) i } ).ToList();

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • KoW
  • Registratie: Juli 2001
  • Laatst online: 17-08-2022

KoW

Parse parsed te veel

Topicstarter
EfBe schreef op vrijdag 01 februari 2008 @ 11:17:
Die test is niet correct, dat kan nl. ook een bug van jouw kant zijn.
Wat, .. is er niet correct aan die testvoorwaarde ?
Je hebt 6 Game objecten, elk met 2 teams, teamA en teamB obgebouwd volgens de query uit de SP.

Als je dan zegt:
C#:
1
testTeam = game[0].teamA;

(In werkelijkheid komt testteam in dit geval ook uit een query, maar het is wel een van de team objecten die aan een van de games is gekoppeld)

Dan kun je daarna toch met een query zoals vermeld: teamA == testTeam || teamB == testTeam
de game objecten terug krijgen waarin dat team speelt :?

Daarnaast geeft de tweede test, die met attachgame hetzelfde aan.
in de init van mijn Game object roep ik per team teamobject.AttachGame(this) aan. Dat lijstje werkt, maar bij alle "s2" teams wordt er maar 1 game geattached. Als s2 nu zelf al een echte kopie was geweest dan had ik bij game1.TeamB (="C") dus game1 en game3 terug moeten zien en bij game2.teamB (="D") game2, game4 en game5.

[quote]pedorus schreef op vrijdag 01 februari 2008 @ 14:07:
En ik vraag me nog af waarom je niet
C#:
1
this.Team1 = Team2;

doet. Of zelfs:
C#:
1
select new Game { Team1 = s1, Team2 = s2 }

[quote]
Team1 = Team2 :?

En die tweede, dat geeft toch gewoon hetzelfde resultaat als de door mij gebruikte:
C#:
1
new Game(s1, s2)
Waarschijnlijk ligt het aan hoe curTeams wordt gemaakt. Test het anders eens zo:
C#:
1
2
3
List<Team> curTeams = 
    ( from i in Enumerable.Range('A', 4)
      select new Team { ID = (char) i } ).ToList();
curTeams is een Enumeratie die op een soortgelijke manier wordt aangemaakt. (geen list overigens)

Maar, je brengt me wel op een idee. Misschien heeft het iets met die enumeratie te maken en moet ik curTeams eerst dwingen naar een array of een list. Het klinkt eigenlijk best logisch dat hij voor elke subquery (wat s2 is) opnieuw door die enumeratie heen loopt en nieuwe objectjes voor me aanmaakt. Hmm, hoe langer ik er over nadenk hoe dommer ik me voel.

Toch even snel testen...

Edit:
|:( 8)7 |:( 8)7 }:O
Juist dus. Op zich inderdaad erg logisch dan dat het s1 deel dan wel werkt. Hij loopt in s1 maar 1 maal over de enumeratie heen, en voor s2 elke keer opnieuw.

Dat het bij s1 wel werkte deed me denken dat het ergens aan de query lag.

[ Voor 9% gewijzigd door KoW op 01-02-2008 20:08 ]

Pagina: 1