C
C#5mo 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_BjornOP5mo ago
reversing the entire numbers array to take the first (last then) 3 seems kinda ineffecient
daniel2
daniel25mo ago
I suggest u use for loop reversely
Alex_is_coding
Alex_is_coding5mo 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_BjornOP5mo 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
2spooky2play5mo ago
ForEach really sucks, dont use it
Jason_Bjorn
Jason_BjornOP5mo ago
can you elaborate?
2spooky2play
2spooky2play5mo 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_BjornOP5mo ago
but isn't reverse expensive? sound like O(n) more space when I only need O(3) more space
2spooky2play
2spooky2play5mo ago
linq is lazy, so i doubt it allocates
Jason_Bjorn
Jason_BjornOP5mo ago
any way to know for sure?
2spooky2play
2spooky2play5mo ago
ask someone in #advanced maybe?
Jason_Bjorn
Jason_BjornOP5mo ago
okay
TheBoxyBear
TheBoxyBear5mo 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
Angius5mo 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
Joschi5mo 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_BjornOP5mo ago
Yeah, we talked about it in #advanced @Joschi
Joschi
Joschi5mo 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