Count of integer values in a List using Lambda Expression - c#

I have a list like this:
myList.Add(1);
myList.Add(1);
myList.Add(3);
myList.Add(4);
myList.Add(5);
myList.Add(6);
I want to find the number of '1's upto an index of 4. So, in this case, the result should be 2.
How do you I put a condition in the Count().
I need the number of integers, which fulfills the criterion n<2 && n>0 (i.e. n==1).

You only care abou the first 4 entries in the list (as you said, values with higher indexes don't matter).
So at first, restrict the search to these four numbers:
myList.Take(4)
from these you want to count only the entries that are 1. You can achieve that using the Count() linq extension that takes a predicate:
int numberOfOnes = myList.Take(4).Count(i => i == 1);

int value = myList.Take(4).Where(w=>w == 1).Sum()
Additionally, 'Where' has a less commonly used overload that provides the index: myList.Where((w,ix)=>ix < 4 && w == 1).Sum().
I would probably use .Take() for readability and performance reasons (see #mjwills comment) though.

Related

Finding the number of odd/even values in a dictionary

I have a dictionary, let's it key value pair be as follow:
a - 1
b - 3
c - 2
I want to find out the number of odd and even value chars. For example, the above will return me 2 odd and 1 even.
I was thinking of iterating but I read iterating is the wrong way if we are using a dictionary. What is the best approach?
use LINQ:
var numOdd = myDic.Count(e => e.Value % 2 == 1);
See this link What is the best way to iterate over a Dictionary in C#? , iterating internally or externally is needed.
The code should be something like following. It first identifies the number of evens, then the number of odd will be total elements minus event numbers.
int evenCounter=0;
foreach(var item in myDictionary.Values)
{
if(item %2 ==0)
evenCounter++;
}
int oddCounter = myDictionary.Count -evenCounter;

Lambda expressions numbers divisible by 9 and 3 c#

I want to write a program that prints from a given array of integers those numbers that are divisible by 3 and 9.I want to use the built-in extension methos and lambda expression.
What I've done:
static void Main(string[] args)
{
List<int> l = new List<int>() {18,3,27,42};
List<int> divBy3 = l.FindAll(x => (x % 9) == 0);
List<int> divBy9 = l.FindAll(x => (x % 3) == 0);
if (divBy9 == divBy3)
{
foreach (var num in divBy9)
{
Console.WriteLine("The numbers divisible by 9 and 3 are: {0}",num);
}
}
else
{
Console.WriteLine("There are no numbers divisible by 9 and 3.");
}
}
And the output should be {27,18}.
My output is always the else branch but I don't understand why.I've tried to put in the original array of integers only the values {18,27} and it should verify the equality.In foreach I put to check only in the divBy9 list because I thought that if the 2 lists are equal would be the same thing to check only in one list, but I don't think is good.
What's wrong? Thank you.
You're comparing two handles, not the items in the lists they represent. And that's not what you want anyway, you want the intersection:
var intersect = divBy9.Intersect(divBy3); // returns an IEnumerable<int>
I don't really know what you're trying to achieve though, the result will always be in divBy9 because of math reasons.
Also you probably should stop using the obsolete FindAll, you can use Where to get a clean Enumerable without allocating memory for the temporary arrays.
You are creating two different lists and comparing them by reference and even though the lists may contain the same elements (they do not) the references will always be different so your code will select the else branch.
As a number divisible by 9 is also divisible by 3 your test seems kind of odd but let us assume that you want to find the numbers divisible by 5 and 9 instead. Then the lambda becomes:
x => x%5 == 0 && x%9 == 0
E.g.
List<int> divBy5And9 = l.FindAll(x => x%5 == 0 && x%9 == 0);
This will filter the source list and only pick the elements that are both divisible by 5 and 9.
The equality is not doing what you think it's doing. It is comparing the object references, and they are not the same because they are different objects.
You need to take each element in divBy3 and make sure that they are also in divBy9 and vice versa. This is set equality.
you are comparing the list instances themselves, ie the object references and these will not be the same, as they are different list instances. See this for more details
You want to compare the lists to see if they contain the same values.
There is an extension method which will help you SequenceEqual
to check only in one list,
Create a dynamic entity to hold the results such as:
var numbers = Enumerable.Range(1, 50) // 1,2,3,...50
.ToList();
numbers.Where(nmb => (nmb % 3) == 0) // Give us all numbers divisible by 3.
.Select(nmb => new
{
Number = nmb,
By3 = true,
By3And9 = (nmb % 9) == 0 // The ones divisible by 9
});
Result:

Ordering a list in-place by two properties

I have a class with two properties, Name and Position.
I would like to order the list with this class by Position, and the elements with the same position should be ordered by Name. I am working on a static list, so I would like to work in-place.
So far I managed to order the list by one property:
list.Sort((x, y) => x.Position.CompareTo(y.Position));
this code is working and I have the list ordered by Position, but I don't know how to implement the second part. I found this question, but I don't understand the answer.
Could anyone please help me?
I would use "OrderBy" and "ThenBy":
IEnumerable<Person> orderedPersons = persons.OrderBy(item => item.Position)
.ThenBy(item => item.Name);
The answer you linked to is correct. The key in sorting by multiple values is that the secondary property only matters if the primaries are equal. A psuedocode implementation of your sort comparison might be:
compare x and y position
if they differ, return order
else compare name, return order
On the Sort method, the code following the (x,y)=> must return 0 if the items are equal, a negative number if the first should be before the second, and a positive number if the second should come before the first. The CompareTo method will return -1, 0, or 1 based on these cases and its arguments. Since you need to compare two different properties, you need two calls to CompareTo. If you decided to add them together, you could have a case like this:
x.position < y.position (compare returns -1)
x.name > y.name (compare returns 1)
result 0, items are considered equal, where your rules
clearly say x should come first in this case.
To solve this issue, we need to make sure the Name comparison only matters when the positions are equal. Since CompareTo only returns -1, 0, or 1, if we multiply the position result by 2 (or any larger number) then the Name comparison will only change the result if the positions are equal. (Because -2 + 1 = -1 and 2 - 1 = 1)
So using the method in your original linked answer, your code would be something like:
list.Sort((x, y) =>
2 * x.Position.CompareTo(y.Position)
+ x.Name.CompareTo(y.Name));
list = list.OrderBy(item => item.Name).ToList();
list.Sort((x, y) => x.Position.CompareTo(y.Position));

Linq sort first two numbers in long type

I want to sort a list of members with respect to the first two digits of the property Civic Number.
If the search year is 82, everyone who has a Civic Number beginning with 82 are left in the list returned.
Here is a method I have written returns a sorted list with respect to first letters in a name.
private static List<Member> GetNameList(string searchString)
{
return _sortMemberList.Where(x => x.FirstName.ToLower().StartsWith(searchString.ToLower())).ToList();
}
I want to write a simular method but with regards on Civic Number. The Civic Number is 10 digits long and is of the data type "long". I know this doesn't work but well, here is something:
private static List<Member> GetMonthList(int searchYear)
{
return _sortMemberList.OrderBy(x => x.CivicNumber > searchYear).ToList();
}
Best regards
Robert Jarlvik
The simplest, very inefficient approach would simply be
_sortMemberList.Where(x => x.CivicNumber.ToString().StartsWith(searchYear.ToString())).ToList()
Otherwise, you could do
_sortMemberList.Where(x => (x.CivicNumber/100000000) == searchYear ).ToList()
assuming you know that all numbers are indeed 10 positions and searchYear is always 2 digits
If the list is already sorted, you can make it more efficient:
_sortMemberList
.SkipWhile(x => x.CivicNumber < searchYear*100000000 )
.TakeWhile(x => (x.CivicNumber/100000000) == searchYear )
.ToList()
Even more efficient would be to use binary-search to locate the lowerbound of the target year, but that can only be done if _sortMemberList allows random access (indexing): see
Can LINQ use binary search when the collection is ordered?
or the List<T>.BinarySearch Method

Populate a list with a specific range of numbers by using LINQ

In order to populate a List<int> with a range of numbers from 1 to n I can use:
for (i=1; i<=n; i++)
{
myList.Add(i);
}
Is there any way to achieve the same result by using LINQ inline expressions?
UPDATE
Assume I have a method getMonthName(i) that given the integer returns the name of the month. Can I populate the list directly with month names somehow by using Enumerable
Enumerable.Range(1,12).Select(getMonthName);
You want to use Enumerable.Range.
myList.AddRange(Enumerable.Range(1, n));
Or
myList = Enumerable.Range(1, n).ToList();
If you're asking this kind of question, you might want to look over the methods of System.Linq.Enumerable. That's where all this stuff is kept. Don't miss ToLookup, Concat (vs Union), and Repeat.
For the month names you can use Select():
var months = Enumerable.Range(1,n).Select(getMonthName);

Categories

Resources