Vulpes
posted
5419 posts
since
Feb 28, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
Assuming that the sequences are already in the correct order, then something like this is probably easiest and should scale OK to more that 3 sequences:
using System; using System.Collections.Generic; using System.Linq;
class Team { public string Name {get; set;} public int Stat1 {get; set;} public int Stat2 {get; set;}
public Team(string name, int stat1, int stat2) { Name = name; Stat1 = stat1; Stat2 = stat2; }
public override string ToString() { return String.Format("Name = {0}, Stat1 = {1}, Stat2 = {2}", Name, Stat1, Stat2); } }
class Program { static void Main() { List<string> teams = new List<string>{"team1", "team2", "team3"}; List<int> stats1 = new List<int>{100, 90, 80}; List<int> stats2 = new List<int>{85, 75, 95};
List<Team> teamList = teams.Select((t, i) => new Team(t, stats1[i], stats2[i])).ToList();
foreach(Team team in teamList) Console.WriteLine(team); Console.ReadKey(); } }
|
|
|
|
|
|
Rich
posted
44 posts
since
Oct 05, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
|
Vulpes, thanks for the response. I will try this out shortly, but as I am new to programming, I have a question about the lamda expression associated with the list<Team>teamList. What do the parameters t and i represent in teams.Select((t, i) => new Team(t, stats1[i], stats2[i])).ToList(); ?
|
|
|
|
|
|
Vulpes
posted
5419 posts
since
Feb 28, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
|
't' represents each string in the 'teams' list and 'i' represents its index in that list.
So, for the first element, 't' will "team1" and 'i' will be 0.
We can then use 'i' to read off the stats for a particular team from the other 2 lists.
|
|
|
|
|
|
Rich
posted
44 posts
since
Oct 05, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
|
Vulpes, thanks! Your answer helped me out and I have a much better understanding of the lambda expression.
|
|
|
|
|
|
Rich
posted
44 posts
since
Oct 05, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
Vulpes, I have another related question. I am now trying to figure out how to perform calculations on a list of objects, and then put the results in a new list. for example:
List<OffenseStats> off = new List<OffenseStats> { new OffenseStats {Team= "Bears", FGA = 50, FGM = 25}, new OffenseStats {Team= "Lions", FGA = 70, FGM = 20} };
How can I then create the equation FGM/FGA for each team, and then put the results in a new List:
List<GoalPercent> GoalPercent = ?????
The GoalPercent class would look something like this:
class GoalPercent() { public string Team {get; set;} decimal GoalPercent {get; set;}
public GoalPercent(string team, decimal gp) { Team = team; GoalPercent = gp; }
}
Thanks in advance.
|
|
|
|
|
|
Vulpes
posted
5419 posts
since
Feb 28, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
|
Off the top of my head, I'd say:
List<GoalPercent> GoalPercent = off.Select( o => new GoalPercent(o.Team, (decimal)o.FGM/o.FGA * 100m) ).ToList();
|
|
|
|
|
|
Rich
posted
44 posts
since
Oct 05, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
|
That did it thanks! I really appreciate your help. Do you have a twitter account that I can follow?
|
|
|
|
|
|
Vulpes
posted
5419 posts
since
Feb 28, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
Afraid not, Rich.
The only 'tweeting' I do is on here :)
|
|
|
|
|
|
Rich
posted
44 posts
since
Oct 05, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
|
Vulpes, I have yet another problem that I am having trouble with. I have this class:
public class NBASeason { public int Season {get;set;} public datetime date {get;set;} public string awayTeam {get;set;} public int awayScore {get;set;} public string homeTeam {get;set;} public int homeScore {get;set;} }
I basically want to calculate each away team's win/loss record, and place it in another class such as:
class AwayRecord { public string AwayTeam {get;set;} public int Wins {get;set} public int Losses {get;set} } I have already made a list that queried the winning away teams:
List<Season> w = this.NBAGetSeasonScores().Where(atw => atw.awayScore > atw.homeScore) .OrderBy(away => away.away).AsEnumerable().ToList();
From this point, I suspect a lambda GroupBy extension method may be needed, as the awayTeam property in the Season class will contain several copies of the same team, but I have yet to correctly figure this out. Hope this makes since. Thanks in advance.
|
|
|
|
|
|
Vulpes
posted
5419 posts
since
Feb 28, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
TBH, Rich, it doesn't make complete sense because what you've called a Season seems to me to be a Game and, in any case, a Season class can't have a property of the same name.
Also, I'd have thought that your AwayRecord class needs an additional property for the name of the team (Team say) and I wasn't clear what the date property was storing unless it's the date of the first away game for that team.
Anyway, for now, I've ignored the Season and date properties and just populated the others with this query which, as you suspected, requires the GroupBy extension method:
List<AwayRecord> awayRecords = this.NBAGetSeasonScores(). GroupBy(s => s.awayTeam).OrderBy(g => g.Key).Select(g => new AwayRecord{Team = g.Key, Wins = g.Count(s => s.awayScore > s.homeScore), Losses = g.Count(s => s.awayScore < s.homeScore)}).AsEnumerable().ToList();
|
|
|
|
|
|
Rich
posted
44 posts
since
Oct 05, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
|
Vulpes, yeah thanks for pointing out those errors. I went back and made updates to the post. Season would be the year such as 1980. The date property represents the date of the game played. Your example makes since, and I think it should work. I'll try to implement it shortly and let you know the result. I really appreciate your insight and time. As a new programmer, it helps me out to see real world examples of the language in action.
|
|
|
|
|
|
Rich
posted
44 posts
since
Oct 05, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
Vulpes, your query worked like a charm. I have yet created another challenge for myself. I added two more properties to the AwayRecord class, which are Spread and Total. The Spread property should hold the average point amount an away team wins or looses by(awayScore - homeScore), while the Total property should hold the average point total of the game(awayScore + homeScore). The Total property was easy enough, but I am having trouble trying to figure out how to correctly query for the Spread property, since the away team isn't always a winner, therefore producing unwanted negative results( awayScore 80 - homeScore 100). I am guessing this may involve a nested lambda expression, and possibly creating another class. Here is what I have so far:
// Get NBA Away Record public List<NBAawayRecord> NBAteamAwayRecord() { List<NBAawayRecord> AwayRecord = this.NBAGetSeasonScores().GroupBy(at => at.away) .OrderBy(g => g.Key).Select(g => new NBAawayRecord { Teams = g.Key, Wins = g.Count(at => at.awayScore > at.homeScore) , Losses = g.Count(at => at.awayScore < at.homeScore) , Spread = g.Average(?????) , Total = g.Average(at => (decimal)at.awayScore + (decimal)at.homeScore) }).AsEnumerable().ToList(); return AwayRecord; }
|
|
|
|
|
|
Vulpes
posted
5419 posts
since
Feb 28, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
To convert the negative values into positive values, all you need to do is to use the absolute value of the difference in scores:
Spread = g.Average(at => (decimal)Math.Abs(at.awayScore - at.homeScore))
|
|
|
|
|
|
Rich
posted
44 posts
since
Oct 05, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
|
worked perfectly, but for some reason I had to move the casting, though:
Spread = g.Average(at => Math.Abs((decimal)at.awayScore - (decimal)at.homeScore))
|
|
|
|
|
|
Vulpes
posted
5419 posts
since
Feb 28, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
Don't understand that as (at.awayScore - at.homeScore) is integral and Math.Abs has an overload for Int32 as well as Decimal.
Might be a LINQ to SQL peculiarity but no matter if it's OK working for you :)
|
|
|
|
|
|
Rich
posted
44 posts
since
Oct 05, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
|
Vulpes, have you thought about writing an article on these type of LINQ scenarios? Particularly on LINQ extension methods involving calculations based on properties from different sequences, objects, etc. I've searched the web, and can only fine basic LINQ examples to learn from, but nothing as specific as what you have taught me thus far. I think a lot of new programmers such as myself would really benefit from such an article.
|
|
|
|
|
|
Vulpes
posted
5419 posts
since
Feb 28, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
|
I have a number of ideas for future articles but, unfortunately, I don't have the time to write them just now :(
A problem with writing an article about something like this is that you need to have a basic grasp of LINQ in order to be able to understand it and I'm not sure that many C# developers do.
Anyway, thanks for the idea, and I'll add it to the list :)
|
|
|
|
|
|
Rich
posted
44 posts
since
Oct 05, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
Vulpes, the following code works for me perfectly, but I am wondering if there is a more concise or efficient way of obtaining the desired results.
public List<NBAstandings> NBAgetStandings() { List<nba_Team_Names> teams = this.NBAgetTeams().AsEnumerable().OrderBy(t => t.Abreviated_Long) .Select(t => t).ToList();
List<NBAstandings> AwayRecord = this.NBAGetSeasonScores().GroupBy(ar => ar.away) .OrderBy(t => t.Key).Select(t => new NBAstandings { Teams = t.Key, Wins = t.Count(at => at.awayScore > at.homeScore), Losses = t.Count(at => at.awayScore < at.homeScore), Spread = t.Sum(at => Math.Abs((decimal)at.awayScore - (decimal)at.homeScore)), Total = t.Sum(at => (decimal)at.awayScore + (decimal)at.homeScore) }).AsEnumerable().ToList();
List<NBAstandings> HomeRecord = this.NBAGetSeasonScores().GroupBy(hr => hr.home) .OrderBy(t => t.Key).Select(t => new NBAstandings { Teams = t.Key, Wins = t.Count(ht => ht.homeScore > ht.awayScore), Losses = t.Count(ht => ht.homeScore < ht.awayScore), Spread = t.Sum(ht => Math.Abs((decimal)ht.homeScore - (decimal)ht.awayScore)), Total = t.Sum(ht => (decimal)ht.homeScore + (decimal)ht.awayScore) }).AsEnumerable().ToList();
List<NBAstandings> TotalSeason = teams.Select((t, i) => new NBAstandings (t.Abreviated_Long, AwayRecord[i], HomeRecord[i])).ToList();
return TotalSeason; } public class NBAstandings { public string Teams { get; set; } public int Wins { get; set; } public int Losses { get; set; } public decimal Spread { get; set; } public decimal Total { get; set; } public NBAstandings AR { get; set; } public NBAstandings HR { get; set; }
// Constructors public NBAstandings() {}
public NBAstandings(string teams, NBAstandings ar, NBAstandings hr) { Teams = teams; Wins = ar.Wins + hr.Wins; Losses = ar.Losses + hr.Losses; Spread = (ar.Spread + hr.Spread)/(ar.Wins + hr.Wins + ar.Losses + hr.Losses); Total = (ar.Total + hr.Total)/(ar.Wins + hr.Wins + ar.Losses + hr.Losses); }
} }
|
|
|
|
|
|
Vulpes
posted
5419 posts
since
Feb 28, 2011
from
|
|
Re: Combining multiple sequences into 1 object
|
|
|
|
|
|
|
|
|
|
In your first query:
List<nba_Team_Names> teams = this.NBAgetTeams().AsEnumerable().OrderBy(t => t.Abreviated_Long).Select(t => t).ToList();
you could omit the Select() method which isn't actually doing anything:
List<nba_Team_Names> teams = this.NBAgetTeams().AsEnumerable().OrderBy(t => t.Abreviated_Long).ToList();
but other than that it's fine.
I woudn't try to cram too much into your LINQ queries as it makes them harder to understand and to maintain. I thought these seemed just right :)
|
|
|
|
|
|