Select max age C# - c#

I created a list<T> that contains a collection of objects that have this properties: X, Y, Z
I want to find out which object in the collection has the greatest Z
I tried to use the Max() function but I don't understand how it's used...

Max is used to find the maximum value of a property. Once you have the maximum value you can select those objects whose value matches using the Where clause.
var maxZ = list.Max( obj => obj.Z );
var maxObj = list.Where( obj => obj.Z == maxZ );

To get the object with the greatest Z value you sort on the Z value in descending order and get the first item:
TypeOfObject oldest = list.OrderByDescending(x => x.Z).First();
Edit:
Changed it to use the IEnumerable.OrderByDescending method instead of List.Sort.
Edit 2:
If you want performance, this is about four times faster than the fastest LINQ solution:
int high = Int32.MinValue;
List<TypeOfObject> highest = new List<TypeOfObject>();
foreach (TypeOfObject v in list) {
if (v.Z >= high) {
if (v.Z > high) highest.Clear();
high = v.Z;
highest.Add(v);
}
}

int maxAge = myList.Max(obj => obj.Z);
The parameter used is a lambda expression. This expression indicates which property to use(in this case, Z) to get the max value. This will get the maximum age. If you want the object which has the greatest age, you could sort by age and get the first result:
MyType maxItem = myList.OrderByDescending(obj => obj.Z).First();
If you do it this way, note that if two or more items all have the maximum age, only one of them is selected.

If can implement either IComparable<T> or IComparable on your class along these lines:
public Int32 CompareTo(MyClass other) {
return Z.CompareTo(other.Z);
}
You can get the maximum value simply by calling (this will require using System.Linq):
MyClass maxObject = list.Max();
This will only perform a single pass over your list of values.

It will largely depend on the type of X, if it is comparable:
var array = new[] {
new { X = "a", Y = "a", Z = 1 },
new { X = "b", Y = "b", Z = 2 }
};
var max = array.Max(x => x.Z);
Console.WriteLine(max);

Related

How can I return a string from an Ienumerable?

I am very new to programming and am taking an Object Oriented Programming class. However, the professor didn't explain how to take an Ienumerable and make it into a string in order to accomplish this question of the assignment:
TODO:
Write a public static C# method named NumSquare that takes a one-dimentional array as input
and creates a LINQ statement that queries the numbers that have a square number graeter than 20 and orders them ascending.
The LINQ query retrieves anonymous objects in which each object contains the number (Num) and its square number (SqrNum).
The method returns the LINQ query as an IEnumerable object.
The anonymous object contains two instance variables named Num and SqrNum.
Input: a one-dimentional integer array.
Output: a LINQ query of type IEnumerable.
Example: Given array A = [3, 4, 10, 5], invoking NumSquare(A) return a LINQ query that once executed will contain:
{Num=5, SqrNum=25},
{Num=10, SqrNum=25}
Here's what I have so far, but I've tried several things over the last 2 1/2 weeks.
public static IEnumerable<object> NumSquare(int[] A)
{
//write your code here
var num = from Number in A
select Number;
var sqrnum = from Number in A
let squarenum = Number * Number
select squarenum;
return (IEnumerable<object>)sqrnum;
}
I know that this return won't get me the whole result that I need, but that's as far as I can get with no errors. I also don't know how to test anything because he didn't show us how to call an IEnumerable. Help?
I think what you are looking for is not a string as output but as the exercise says an anonymous object. An anonymous object can be something like this:
var o = new { Num = 4, SqrNum = 16 };
Its just an object that basically has no explicit type and some read-only variables.
So what you want to do is to convert your array into a IEnumerable<{int Num, int SqrNum}> which you would have to declare as IEnumerable<object> and not a string.
You could do something like this:
static IEnumerable<object> NumSqr(int[] a)
{
return a
.Where(x => x * x > 20)
.OrderBy(x => x)
.Select(x => new { Num = x, SqrNum= x * x });
}
Alternatively:
static IEnumerable<object> NumSqr(int[] a)
{
return from number in a
where number * number > 20
orderby number
select new { Num = number, SqrNum = number * number };
}
In order to print out the result of the function you could do this:
var a = new int[] { 3, 4, 10, 5 };
var result = NumSqr(a);
foreach (var obj in result)
{
Console.WriteLine(obj);
}
The output should look like this:
{ Num = 5, SqrNum = 25 }
{ Num = 10, SqrNum = 100 }

Is there a way to find the closest number in an Array to another inputed number?

So I have a Visualstudio Forms where I have a NumericUpDown function that will allow users to input a 5 digit number such as 09456. And I need to be able to compare that number to an already existing array of similar 5 digit numbers, so essentially I need to get the inputted number and find the closest number to that.
var numbers = new List<float> {89456f, 23467f, 86453f, };
// the list is way longer but you get the idea
var target = numericUpDown.3 ;
var closest = numbers.Select(n => new { n, (n - target) })
.OrderBy(p => p.distance)
.First().n;
But the first problem I encounter is that I cannot use a "-" operation on a float. Is there any way I can avoid that error and be able to still find the closest input?
Anonymous type members need names, and you need to use the absolute value of the difference. eg
var numbers = new List<float> { 89456f, 23467f, 86453f, };
var target = 3;
var closest = numbers.Select(n => new { n, distance = Math.Abs(n - target) })
.OrderBy(p => p.distance)
.First().n;
Well, apart from some issues in your sample(like no distance property on float) it should work:
int target = 55555;
float closest = numbers.OrderBy(f => Math.Abs(f - target)).First();
Demo: https://dotnetfiddle.net/gqS50L
The answers that use OrderBy are correct, but have less than optimal performance. OrderBy is an O(N log N) operation, but why sort the whole collection when you only need the top element? By contrast, MinBy will give you the result in O(N) time:
var closest = numbers.MinBy(n => Math.Abs(n - target));
Apart from the compilation errors, using LINQ for this is very slow and time consuming. The entire list has to be scanned once to find the distance, then it needs to be sorted, which scans it all over again and caches the results before returning them in order.
Before .NET 6
A faster way would be to iterate only once, calculating the distance of the current item from the target, and keep track of which number is closest. That's how eg Min and Max work.
public static float? Closest(this IEnumerable<float> list, float target)
{
float? closest=null;
float bestDist=float.MaxValue;
foreach(var n in list)
{
var dist=Math.Abs(n-target);
if (dist<bestDist)
{
bestDist=dist;
closest=n;
}
}
return closest;
}
This will return the closest number in a single pass.
var numbers = new List<float> { 89456f, 23467f, 86453f, };
var closest=numbers.Closest(20000);
Console.WriteLine($"Closest is {closest}");
------------------
Closest is 23467
Using MoreLINQ and MinBy
The same can be done in a single line using the MinBy extension method from the MoreLINQ library:
var closest=numbers.MinBy(n=>Math.Abs(n-target));
Using MinBy
In .NET 6 and later, Enumerable.MinBy was added to the BCL:
var closest=numbers.MinBy(n=>Math.Abs(n-target));
The code is similar to the explicit loop once you look past the generic key selectors and comparers :
while (e.MoveNext())
{
TSource nextValue = e.Current;
TKey nextKey = keySelector(nextValue);
if (nextKey != null && comparer.Compare(nextKey, key) < 0)
{
key = nextKey;
value = nextValue;
}
}

Return from list the double value that has the highest absolute value, without making the return value absolute

Short of iterating the collection, is there a way to return the double in a set that has the highest absolute value without making the values in the set actually absolute?
double[] vals = new double[] { 2.3, 1.7, -3.8};
vals.Max(v => Math.Abs(v)); // This returns 3.8 instead of -3.8
One approach to consider:
var max = vals
.OrderByDescending(z => Math.Abs(z))
.FirstOrDefault();
Alternatively, consider using MoreLinq's MaxBy. It is faster than both my and Samvel's solution, especially for larger sets of inputs.
var max = vals.MaxBy(z => Math.Abs(z));
Here are two ways of doing this:
First with LINQ:
double[] vals = new double[] { 2.3, 1.7, -3.8};
var max = vals.Max(x => Math.Abs(x));
Console.WriteLine(vals.Where(z => Math.Abs(z) == max).First());
Second with For loop:
int index =0;
for(int i=0;i<vals.Length;i++)
{
if(Math.Abs(vals[i])>=Math.Abs(vals[index]))
index=i;
}
Console.WriteLine(vals[index]);

Rotate List<T> based on a condition

Say I have a List<Point> { {5,2}, {7,2}, {3,9} }
I want my output to always start with the point with the smallest X value
So something like:
var output = input.Rotate((x, y) => x.X < y.X));
output = `List<Point> { {3,9}, {5,2}, {7,2} }`
It's not hard to do manually:
Find the index of the object meeting the condition
Create a new List
Add everything from index to end to that list
Add everything from 0 to index-1
I'm just wondering if there is a LINQ way of doing this?
First find the minimum X value:
var minX = input.Min(p => p.X);
Next get the first occurrence where X is that minimum value:
var index = input.FindIndex(p => p.X == minX);
Now create a new list by splitting the original into two sections:
var newInput = input.Skip(index).Concat(input.Take(index));
You can't do it in one step, you will need at least two iterations through the array. But you could do this (kinda hacky) approach:
var range = Enumerable.Range(0, list.Count);
var index = range.Aggregate((p,c) => list[p].X> list[c].X? c : p);
var rotated = range.Select(i => list[(i + index) % list.Count]).ToList();
Here's an example (using Tuple rather than Point, but it's the same principle)
The first step is to find the index of the lowest value in your array. The second step them builds your new array starting at that index and looping around.
If you wanted to encapsulate it in an extension method, you could do something like this:
public static IEnumerable<T> Rotate<T>(this List<T> list, Func<T,T, bool> comparer)
{
var range = Enumerable.Range(0, list.Count);
var index = range.Aggregate((p,c) => predicate(list[p],list[c]) ? p : c);
return range.Select(i => list[(i + index) % list.Count]);
}
Which you'd call like this:
var output = input.Rotate((x, y) => x.X < y.X));
You pass in a function which, if it evaluates to true, will select x instead of y

In C#, what does a call to Sort with two parameters in brackets mean?

I recently came across an implementation of Djikstra's Shortest Path algorithm online and found the following call.
given a List of nodes of type int and a Dictionary of distances, of type , what does the following call mean
nodes.Sort((x, y) => distances[x] - distances[y]);
The full code is as follows:
public List<int> shortest_path(int start, int finish)
{
var previous = new Dictionary<int, int>();
var distances = new Dictionary<int, int>();
var nodes = new List<int>();
List<int> path = null;
foreach (var vertex in vertices)
{
if (vertex.Item1 == start)
{
distances[vertex.Item1] = 0;
}
else
{
distances[vertex.Item1] = int.MaxValue / 2;
}
nodes.Add(vertex.Item1);
}
while (nodes.Count != 0)
{
nodes.Sort((x, y) => distances[x] - distances[y]);
var smallest = nodes[0];
nodes.Remove(smallest);
if (smallest == finish)
{
path = new List<int>();
while (previous.ContainsKey(smallest))
{
path.Add(smallest);
smallest = previous[smallest];
}
break;
}
if (distances[smallest] == int.MaxValue)
{
break;
}
foreach (var neighbor in vertices[smallest].Item2)
{
var alt = distances[smallest] + neighbor.Item2;
if (alt < distances[neighbor.Item1])
{
distances[neighbor.Item1] = alt;
previous[neighbor.Item1] = smallest;
}
}
}
return path;
}
I searched for the answer a lot but there doesn't seem to be any clear explanation of what it means.
I do know that in general in LINQ, a call to Array.Select((x,i)=>...) means that x is the actual element in the array and i is the index of element x in the array, but this doesn't seem to be the case above.
Would appreciate any explanation thanks.
In C#, what does a call to Sort with two parameters in brackets mean?
You have this line of code:
nodes.Sort((x, y) => distances[x] - distances[y]);
You are not passing two parameters to the sort method but you are passing one parameter which is a delegate that takes 2 parameters. You are essentially doing the following but using a lambda notation:
var nodes = new List<int>();
nodes.Sort(SortIt);
And here is the SortIt method:
private int SortIt(int x, int y)
{
return distances[x] - distances[y];
}
Keep in mind if you did it using the above approach, distances will have to be a class level field so the SortIt method can access it. With lambda expressions, this is what you have, it will just capture the distances variable and this is called a closure. Read this article if you want to know what closures are.
Sorting is implemented by comparing two items at a time.
The two parameters in parentheses are the two items the callback function should compare.
List.Sort Method takes an optional comparison delegate as a comparer.
https://msdn.microsoft.com/en-us/library/w56d4y5z(v=vs.110).aspx
in your example:
(x, y) => distances[x] - distances[y]) is a delegate that Sort uses as a comparer.
if distances[x] - distances[y] < 0; x is bigger;
if distances[x] - distances[y] > 0; y is bigger;
if distances[x] - distances[y] > 0; both are even;
This method will sort the elements in the entire List using the specified System.Comparison.
Where System.Comparison is a delegate
public delegate int Comparison<in T>(
T x,
T y
)
Think of it like this, you are passing the sort method a way to decide which element in the array is a precedent to the other. The sort function will use the compare function you specified to determine the precedence of each element in the returned sorted list. Therefore this function will get two elements and it will return a value indicating the result of the precendence.
let x be the first argument and y the second argument.
x < y -> the function will return a number less than 0
x = y -> the function will return 0
x > y -> the function will return a number bigger than 0
In conclusion, this function you pass to the Sort method will help the Sort function to sort the array as you wish it should sort it.

Categories

Resources