Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

To .Take() or not to .Take(), that is the question

I have a collection that represents the population (M, F) for each years of age.

In order to project population through time, I have to first make the calculations with the women so that I may calculate the percentage of new born men and women based on a statistical constant of masculinity birth rate.

That said, I have a first matrix which contains both men and women population per year of age.

// Where 1 is the evaluation Id and 2009 the year I want the 
// initial population information for.
IList<AnnualPopulation> initialPopulation = 
    LoadMatrix<AnnualPopulation>(1, 2009);

Now, in order to project the women's population first, I use the following:

IList<AnnualPopulation> initialWomenPopulation = (
        from w in initialPopulation
        where String.Equals("F", w.Gender)
        select w
    ).FirstOrDefault();

And I have to consider mortality rates for both the current (initial year (2009)) and the year for which I wish to project, from which I already have mortality rates for each year of age.

IList<AnnualDeathRate> deathRates = LoadMatrix<AnnualDeathRate>(1, 2009)

This loads the deather rates from 2009 and later for each year of age. Hence, in order to only consider 2009 and 2010, let's say, I used the following Linq code.

AnnualDeathRate[] femaleDeathRates = (
        from fdr in deathRates
        where (string.Equals("F", fdr.Gender))
        select fdr
    ).TakeWhile(dr => 
        initialWomenPopulation.Year == dr.Year || 
        dr.Year == initialWomenPopulation.Year + 1
    ).ToArray()

Questions

  1. Would it have been best if I had used .Take(2) along with a supplemental where condition on the dr.Year?
  2. Are there any better alternatives?
  3. Is my approach worth considerations?
like image 900
Will Marcouiller Avatar asked Nov 06 '22 00:11

Will Marcouiller


1 Answers

Actually #1 may produce a different result than your current code. For instance if the order was random (I don't see any sorting anywhere) the current code may return any number of results (e.g. no results if the first element doesn't match either condition, even if subsequent ones do)

It sounds like approach #1 would be more correct (unless you actually want the behavior of TakeWhile) You're saying you want the first 2 results that match the given condition, whether or not they are the first ones of the initial list.

For example

var numbers = new[] {2, 3, 1, 4};
Console.WriteLine("TakeWhile");

foreach(var n in numbers.TakeWhile(x => x == 1 || x == 2))
{
    Console.Write(n);
}
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("WhereTake2");

foreach (var n in numbers.Where(x => x == 1 || x == 2).Take(2))
{
    Console.Write(n);
} 

Prints:

TakeWhile
2

WhereTake2
21
like image 142
Davy8 Avatar answered Nov 20 '22 12:11

Davy8