How to fill in missing values from a list
I have an object that contains a date and a counter.
public class Stat
{
public DateTime Stamp {get; set;}
public int Count {get; set ;}
}
I have a Serie object that contains a list of thoses Stat plus some additional information like name etc.
public class Serie
{
public string Name { get; set; }
public List<Stat> Data { get; set; }
...
}
Please note that I have a list of episodes, but not all the same stamps in the ranks. I need to fill in missing stamps in everything with default.
I was thinking about an extension method with a signature like this (please provide a better name if you find it :)):
public static IEnumerable<Serie> Equalize(this IEnumerable<ChartSerie> series, int defaultCount)
this question seems to be referring to the same issue, but when querying the DB directly. of course, I could skip the dates and create another list. But is there a more elegant way to achieve this?
i.e:.
Series A:
05/01/2010 1
05/03/2010 3
Series B:
05/01/2010 5
05/02/2010 6
I have to get:
Series A:
05/01/2010 1
05/02/2010 0
05/03/2010 3
Series B:
05/01/2010 5
05/02/2010 6
05/03/2010 0
a source to share
Not sure if this is neat enough for you ;-), but since I like Linq, this is what I would do (using your naming scheme):
public static IEnumerable<Serie> Equalize(
this IEnumerable<Serie> series,
int defaultCount)
{
var allStamps = series
.SelectMany(s => s.Data.Select(d => d.Stamp))
.Distinct()
.OrderBy(d => d)
.ToList();
return series.Select(serie => new Serie(
serie.Name,
allStamps.Select(d =>
serie.Data.FirstOrDefault(stat => stat.Stamp == d)
??
new Stat(d, defaultCount))
));
}
Your classes need several constructors to compile this code:
public class Stat
{
public Stat() {}
public Stat(DateTime stamp, int count)
{
Stamp = stamp;
Count = count;
}
public DateTime Stamp { get; set; }
public int Count { get; set; }
}
public class Serie
{
public Serie() {}
public Serie(string name, IEnumerable<Stat> data)
{
Name = name;
Data = new List<Stat>(data);
}
public string Name { get; set; }
public List<Stat> Data { get; set; }
}
When called series.Equalize(0)
, the above code will leave the original instances intact and return a sequence of newly created Serie
-instations with theirs Data
padded by default.
There is nothing magical about it. Just sweetness of Linq ... (and a null coalescing operator!)
I haven't tried this with loads and lots of data, so your movement may vary.
a source to share