Manipulating array's index using Lambda Expression - c#

I was going through some tutorial about LINQ and I bumped into following code, I could not understand what 'n' is doing here,though I understand Author is trying to get every third element.It clearly shows I lack understanding of Lambda expression.(It would be great if some one can provide beginner to master link for that, as of now when I try to find them I never find them with solid fundamentals and result is botched understanding). In following array every third element is in 'Yen'(currency).
static double[] ExchangedPrices = {827.70, 604.50, 111869.70,
1869.00, 1,365.00, 252609.00,
521.36, 380.77, 70465.88,
455.68, 332.80, 61588.48,
2018.34, 1474.07, 272793.66,
920.26, 672.10, 124379.86,
1873.45, 1368.25, 253210.45,
149.34, 109.07, 20184.66,
455.68, 332.80, 61588.48,
525.28, 383.63, 70995.16,
9.08, 6.63, 1226.96,
311.50, 227.50, 42101.50};
IEnumerable<double> yenQuery = ExchangedPrices.Where((n, index) => index%3 == 0);

Using Where will essentially loop through the array and return elements that meet a given condition.
n represents the element itself and index represents the index of the element on each iteration.
So the where statement is going through each of the elements of the array one by one and each time testing if the index of that element is divisible by 3.
The msdn Lambda article is a good start to gain a better understanding of Lambdas.

Here n represents each item in your ExchangedPrices array. index is variable which holds the (zero based) index value of the sequence and using that we are checking an if condition index%3==0. So when the code runs, This condition will be evaluated againist each item in the iteration and will return true or false. The LINQ Where clause takes this predicate and will eventually return a subset of original data based on the result of this if condition. So if the predicate expression returns true, the corresponding item (value of n at that iteration) will be used to build the subset data which will be returned.
Since the if condition expression is going to return true for 12 times while evaluating 37 items in the loop, It will get those 12 items from your original array and will be stored to your yenQuery variable.

ExchangedPrices.Where((n, index) => index%3 == 0);
This line is creating a lambda expression of n and index. n represents the value of the double and index represents the index of that double in the array ExchangedPrices. You could use n inside of your lambda expression just like you use index.
ExchangedPrices.Where((n, index) => n%3 == 0);
This line would get you all of the values in your array that are divisible by 3 as opposed to every 3rd element in the array by index.

Related

Sort a list of Expressions in Optano C#

Edit: To reword my opening explanation to hopefully make it clearer: "How can I write an expression that represents the mean of the lowest N expressions in an unordered list?" The list includes negative values.
TLDR: how do I make a list of Expressions that is sorted by the values to which each Expression would evaluate?
Full question:
I'm using Optano with the Gurobi solver in C# (using VS2019) to minimise the sum of the lowest 5% of a set of weighted values (the weights being the variables added to the model).
To the find the lowest 5% I need to sort the values calculated by the model. One way or another, I need to be able to compare two values, but I can't work out how. If I have List the Sort() method doesn't work for obvious reasons.
Instead, because it's more efficient and is much simpler code than a sorting algorithm (which I have also tried to no avail, using selection sorting), I have a little foreach that finds the correct position in a list into which to insert the new value so that I end up with a sorted list.
Expression[] expressionPairForMin = new Expression[2];
expressionPairForMin[0] = weightedValueTemp; //The new Expression I want to insert into the sorted list.
foreach (Expression weightedValue in allWeightedValues)
{
expressionPairForMin[1] = weightedValue;
//if (weightedValueTemp < weightedValue) { break; } //What I want to do, which doesn't work of course.
if (Expression.Equals(Expression.Minimum(expressionPairForMin), weightedValueTemp)) { break; } //One of several ideas I've tried.
insertPosition++;
}
portfolioWeightedReturns.Insert(insertPosition, weightedValueTemp);
The if I have there is trying to say: if the minimum of the two Expressions is the same as the first Expression, then the first Expression must be the smaller of the two.
Later, I take the sum (using Expression.Sum) of the first n values (which is what's returned as an Expression for the Objective).
My code works if I use Expression.Evaluate on the objective with hardcoded weights as input variables and use the double values more directly, but not when I run the solver. It just doesn't sort the list in that case, as the if never returns true and so weightedValueTemp is always inserted at the end of the list.

Does list.count physically iterate through the list to count it, or does it keep a pointer

I am stepping through a large list of object to do some stuff regarding said objects in the list.
During my iteration, I will remove some objects from the list depending on certain criteria.
Once all is done, I need to update the UI regarding the number of objects in my list. (List of T).
QUESTION:
When I call list.count, does .net actually iterate through the list to
count it, or does it store the count as a property/variable?
If .net physically re-iterates through the list, I may just as well keep a counter on my own iteration through the list, and save the overhead?
Thanks
It simply keeps an internal int to track the number of items. So no iteration.
The documentation says retrieving Count is an O(1) operation:
http://msdn.microsoft.com/en-us/library/27b47ht3%28v=vs.110%29.aspx
You can see for yourself:
http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs
List is implemented as an array list, and it keeps track of its own size, so invoking the .Count property doesn't require any iteration.
If you call the LINQ .Count() extension method, this will check whether the underlying IEnumerable<> implements ICollection (which a List<> does), and use the .Count property on that interface if possible. So this won't cause any iteration to occur either.
Incidentally, there are other problems you're going to encounter if you attempt to remove items from your list while iterating through it. It's not really clear how iteration should behave when you are removing elements out from under the iterator, so List<>s will avoid this issue entirely by throwing an exception if the list has been modified since its enumerator was created.
You can use a decompiler, such as the freely-available ILSpy, to answer these questions. If you're referring to the List<T> type, then the Count getter simply involves reading a field:
public int Count
{
get { return this._size; }
}
As stated here under the remarks tab
http://msdn.microsoft.com/en-us/library/27b47ht3(v=vs.110).aspx
Retrieving the value of this property is an O(1) operation.
Which means no iteration is occurring.
You tagged your question with both vb.net and c#, so in reply to "If .net physically re-iterates through the list, I may just as well keep a counter on my own iteration through the list, and save the overhead?"
If your iteration is with a For i = first To last then VB.NET will evaluate first and last when it enters the loop:
Dim first As Integer = 1
Dim last As Integer = 3
For i = first To last
Console.Write(i.ToString() & " ")
last = -99
Next
outputs: 1 2 3
If you do the equivalent in C#, first and last are evaluated on every iteration:
int first = 1;
int last = 1;
for (int i = first; i <= last; i++)
{
Console.Write(i.ToString() + " ");
last = -99;
}
outputs: 1
If your .Count() function/property is expensive to evaluate and/or you don't want it to be re-evaluated on each iteration (for some other reason), then in C# you could assign it to a temporary variable.

Sorting without comparing elements

given size of array 5, with five numbers in it, sort them from smallest to largest without comparing.(hint, access time O(n)
I tried to search a lot but didnt knew, how it can be done. O(n), means which algo/data structure.i am unaware.
I suppose you need Counting sort, it has linear time, but takes some memory and depends on min/max value of your initial array
The Counting Sort will do this for you, although if I were in an interview and on the spot I'd probably do something like the below which is vaguely similar as I can never remember these "classic" algorithms off the top of my head!
The key idea here is to use the each actual unsorted integer value as an index into a target array that contains N elements where N is the max. of the values to be sorted.
I am using a simple class to record both the value and the number of times it occurred so you can reconstruct an actual array from it if you need to keep discrete values that occurred multiple times in the original array.
So all you need to do is walk the unsorted array once, putting each value into the corresponding index in the target array, and (ignoring empty elements) your values are already sorted from smallest to largest without having ever compared them to one another.
(I personally am not a fan of interview questions like this where the answer is "oh, use Counting Sort" or whatever - I would hope that the interviewer asking this question would be genuinely interested to see what approach you took to solving a new problem, regardless of if you got a strictly correct answer or not)
The performance of the below is O(n) meaning it runs in linear time (1 element takes X amount of time, 10 elements takes 10X,etc) but it can use a lot of memory if the max element is large,cannot do in place sorting, will only work with primitives and it's not something I'd hope to ever see in production code :)
void Main()
{
//create unsorted list of random numbers
var unsorted = new List<int>();
Random rand = new Random();
for(int x=0;x<10;x++)
{
unsorted.Add(rand.Next(1,10));
}
//create array big enough to hold unsorted.Max() elements
//note this is indirectly performing a comparison of the elements of the array
//but not for the sorting, so I guess that is allowable :)
var sorted = new NumberCount[unsorted.Max()+1];
//loop the unsorted array
for (int index=0;index<unsorted.Count;index++)
{
//get the value at the current index and use as an index to the target array
var value = unsorted[index];
//if the sorted array contains the value at the current index, just increment the count
if (sorted[value]!=null && sorted[value].Value!=0)
{
sorted[value].Count++;
}
else
{
//insert the current value in it's index position
sorted[value]=new NumberCount{Value=value,Count=1};
}
}
//ignore all elements in sorted that are null because they were not part of the original list of numbers.
foreach (var r in sorted.Where(r=>r!=null))
{
Console.WriteLine("{0}, occurs {1} times",r.Value,r.Count);
}
}
//just a poco to hold the numbers and the number of times they occurred.
public class NumberCount
{
public int Value{get;set;}
public int Count{get;set;}
}

LINQ - selecting second item in IEnumerable

I have
string[] pkgratio= "1:2:6".Split(':');
var items = pkgratio.OrderByDescending(x => x);
I want to select the middle value and have come up with this. Is this a correct way to select the second value in an IEnumberable?
pkgratio.Skip(1).Take(1).First();
While what you have works, the most straightforward way would be to use the array's index and reference the second item (at index 1 since the index starts at zero for the first element): pkgratio[1]
Console.WriteLine(pkgratio[1]);
A more complete example:
string[] pkgratio = "1:2:6".Split(':');
for (int i = 0; i < pkgratio.Length; i++)
Console.WriteLine(pkgratio[i]);
With an IEnumerable<T> what you have works, or you could directly get the element using the ElementAt method:
// same idea, zero index applies here too
var elem = result.ElementAt(1);
Here is your sample as an IEnumerable<string>. Note that the AsEnumerable() call is to emphasize the sample works against an IEnumerable<string>. You can actually use ElementAt against the string[] array result from Split, but it's more efficient to use the indexer shown earlier.
var pkgratio = "1:2:6".Split(':').AsEnumerable();
Console.WriteLine(pkgratio.ElementAt(1));
I don't think you need to .Take(1).
pkgratio.Skip(1).First()
pkgratio.ElementAt(1); for your scenario.
However, your method is only applicable if you were using some data that implemented IQueryable or you needed to take a range of items starting at a specific index eg:
pkgratio.Skip(5).Take(10);
Well, the Take(1) isn't strictly necessary if you're going to just First() it, so I might go with
pkgratio.Skip(1).First();
However, that First() will throw an exception if there no value, so you might want to try FirstOrDefault() and then check for null.

Please explain System.Linq.Enumerable.Where(Func<T, int, bool> predicate)

I can't make any sense of the MSDN documentation for this overload of the Where method that accepts a predicate that has two arguments where the int, supposedly, represents the index of the source element, whatever that means (I thought an enumerable was a sequence and you couldn't see further than the next item, much less do any indexing on it).
Can someone please explain how to use this overload and specifically what that int in the Func is for and how it is used?
The int parameter represents the index of the current item within the current iteration. Each time you call one of the LINQ extension methods, you aren't in theory guaranteed to get the items returned in the same order, but you know they're all be returned once each and thus can be assigned indices. (Well, you are guaranteed if you know the query object is a List<T> or such, but not in general.)
Example:
var result1 = myEnumerable.Where((item, index) => index < 4);
var result2 = myEnumerable.Take(4);
// result1 and result2 are equivalent.
You can't index an IEnumerable<T> in the same way you can an array, but you might be able to use the index to filter the list in some way, or possibly to index some data in another collection which will be used in the condition.
EDIT: As an example, to skip every other element you could use:
var results = sequence.Where((item, idx) => idx % 2 == 0);

Categories