C
C#6mo ago
Jason_Bjorn

LINQ help

I have a collection of ints, how can I take the last three that are bigger than 100? is there a better way than this?
using System;
using System.Linq;

class Program
{
static void Main()
{
int[] numbers = { 80, 120, 110, 90, 10, 140, 150, 50, 22, -800 };

var result = numbers.Where(num => num > 100).Reverse().Take(3).Reverse().ToArray();

Console.WriteLine("Last 3 elements over 100:");
foreach (var num in result)
{
Console.WriteLine(num);
}
}
}
using System;
using System.Linq;

class Program
{
static void Main()
{
int[] numbers = { 80, 120, 110, 90, 10, 140, 150, 50, 22, -800 };

var result = numbers.Where(num => num > 100).Reverse().Take(3).Reverse().ToArray();

Console.WriteLine("Last 3 elements over 100:");
foreach (var num in result)
{
Console.WriteLine(num);
}
}
}
17 Replies
Jason_Bjorn
Jason_BjornOP6mo ago
reversing the entire numbers array to take the first (last then) 3 seems kinda ineffecient
daniel2
daniel26mo ago
I suggest u use for loop reversely
Alex_is_coding
Alex_is_coding6mo ago
I was curious to try, and got this
int[] numbers = { 80, 120, 110, 90, 10, 140, 150, 50, 22, -800 };

IOrderedEnumerable<int> sortedNum = numbers.OrderDescending();
string aStr = string.Empty;
for(int i = 0; i <= 2; i++)
{
if (sortedNum.ElementAt(i) >= 100)
{
aStr += sortedNum.ElementAt(i).ToString() + "\r\n";
}
}
MessageBox.Show( aStr );
int[] numbers = { 80, 120, 110, 90, 10, 140, 150, 50, 22, -800 };

IOrderedEnumerable<int> sortedNum = numbers.OrderDescending();
string aStr = string.Empty;
for(int i = 0; i <= 2; i++)
{
if (sortedNum.ElementAt(i) >= 100)
{
aStr += sortedNum.ElementAt(i).ToString() + "\r\n";
}
}
MessageBox.Show( aStr );
Jason_Bjorn
Jason_BjornOP6mo ago
Why sort them seems like a waste of time? Just traverse in reverse then and pick until you have 3 or reach end (start) like this?
int[] numbers = [80, 120, 110, 90, 10, 140, 150, 50, 22, -800];

int[] threeOver100 = new int[3];
int insertIndex = threeOver100.Length - 1;

for (int i = numbers.Length - 1; i >= 0; i--)
{
if (numbers[i] > 100)
{
threeOver100[insertIndex] = numbers[i];
insertIndex--;
if (insertIndex < 0)
{
break;
}
}
}

Array.ForEach(threeOver100, Console.WriteLine);
int[] numbers = [80, 120, 110, 90, 10, 140, 150, 50, 22, -800];

int[] threeOver100 = new int[3];
int insertIndex = threeOver100.Length - 1;

for (int i = numbers.Length - 1; i >= 0; i--)
{
if (numbers[i] > 100)
{
threeOver100[insertIndex] = numbers[i];
insertIndex--;
if (insertIndex < 0)
{
break;
}
}
}

Array.ForEach(threeOver100, Console.WriteLine);
2spooky2play
2spooky2play6mo ago
ForEach really sucks, dont use it
Jason_Bjorn
Jason_BjornOP6mo ago
can you elaborate?
2spooky2play
2spooky2play6mo ago
the last Reverse().ToArray() seems unnecessary its a long story, but 1) its slower (iirc) 2) it requires an allocated list (sometimes you dont need to allocate) var result = numbers.Where(num => num > 100).Reverse().Take(3) is all you need
Jason_Bjorn
Jason_BjornOP6mo ago
but isn't reverse expensive? sound like O(n) more space when I only need O(3) more space
2spooky2play
2spooky2play6mo ago
linq is lazy, so i doubt it allocates
Jason_Bjorn
Jason_BjornOP6mo ago
any way to know for sure?
2spooky2play
2spooky2play6mo ago
ask someone in #advanced maybe?
Jason_Bjorn
Jason_BjornOP6mo ago
okay
TheBoxyBear
TheBoxyBear6mo ago
My guess would be to put Reverse first. Linq also has a lot of shortcuts for common collection types and I wouldn't be surprised if Reverse didn't simply enumerate with a decreasing index for arrays. It's always possible to look into the underlying code of .NET to confirm for yourself, in this case by looking at the body of Reverse
Angius
Angius6mo ago
If you don't want to reverse:
var result = nubers
.Where(n => n > 100)
.Skip(numbers.Length - 3);
var result = nubers
.Where(n => n > 100)
.Skip(numbers.Length - 3);
Joschi
Joschi6mo ago
Reverse() indeed completely enumerates the IEnumerable<T> and copies the result into a new T[]. It then returns the elements of the newly created array in reverse order.
Jason_Bjorn
Jason_BjornOP6mo ago
Yeah, we talked about it in #advanced @Joschi
Joschi
Joschi6mo ago
Did they by any chance elaborate on why? Because for IList<T> implementations shouldn't it be possible to just yield the content in reverse order using the index?
Want results from more Discord servers?
Add your server