This works:
exists = dt.AsEnumerable().Where(c => c.Field<int>("GENARTNR").Equals(int.Parse(nodeID))).Count() > 0;
Now nodeID is a string which can have more than 1 nodeIdz so 100,178,111,200 or 100 or 200,100
Now I want to do something like:
exists = dt.AsEnumerable().Where(nodeID.Contains(c => c.Field<string>("GENARTNR")));
But I am getting :
Cannot convert lambda expression to type 'char' because it is not a delegate type
Any work around this or some other suggestion?
First, don't use Field<string>("GENARTNR") is it's actually an int column.
You can use this approach that uses Contains with an int[]:
int[] nodeIDs = ParseNodeId(nodeId);
exists = dt.AsEnumerable().Any(r => nodeIDs.Contains(r.Field<int>("GENARTNR")));
private static int[] ParseNodeId(string nodeId)
{
return nodeId?.Trim().Split(',')
.Select(n => int.TryParse(n.Trim(), out int id) ? id : (int?)null)
.Where(x => x.HasValue)
.Select(x => x.Value)
.ToArray() ?? Array.Empty<int>();
}
Related
I have method which return List and I wanna try to populate ValueTuple from another standard list I get error:
Cannot implicitly convert type 'System.Collections.Generic.List<(long PaymentId, long TransactionId)>' to 'System.Collections.Generic.List>'
The code looks like below:
public async Task<List<ValueTuple<(long, long)>>> CreditTransactionAsync(CancellationToken cancellationToken)
{
List<(long PaymentId, long TransactionId)> paymentTransactionList = new List<ValueTuple<long, long>>();
var paymentTransactions = _dbContext.PaymentTransactions
.AsEnumerable()
.Where(x => transactionIdsList.Any(a => a.TransactionId == x.TransactionId))
.Select(x => new
{
PaymentId = x.PaymentId,
TransactionId = x.TransactionId
})
.ToList();
// This line shows error..
paymentTransactionList = paymentTransactions.Select(x => (PaymentId: x.PaymentId, TransactionId: x.TransactionId));
return paymentTransactionList;
}
You can rewrite your Select statement a little bit and map transactions to list of tuple (long, long) directly, without intermediate anonymous type
.Select(x => (x.PaymentId, x.TransactionId))
The full code
var paymentTransactions = _dbContext.PaymentTransactions
.AsEnumerable()
.Where(x => transactionIdsList.Any(a => a.TransactionId == x.TransactionId))
.Select(x => (x.PaymentId, x.TransactionId))
.ToList();
return paymentTransactions;
You also should properly declare the return type of your method, like Task<List<(long paymentId, long transactionId)>>
ValueTuple<(long, long)> is a value tuple that contains a single element that is a value tuple that contains two elements.
You probably meant List<(long, long)>, not List<ValueTuple<(long, long)>>, however personally I'd say "don't use ValueTuple<...> on public APIs", but if you do: at least name them.
Also: AsEnumerable() on a db-context is usually a terrible mistake - especially before a Where:
public async Task<List<(long PaymentId, long TransactionId)>> CreditTransactionAsync(CancellationToken cancellationToken = default)
{
var localList = transactionIdsList.Select(a => a.TransactionId).ToList();
return _dbContext.PaymentTransactions
.Where(x => localList.Contains(x.TransactionId))
.Select(x => new { x.PaymentId, x.TransactionId })
.AsEnumerable()
.Select(x => (x.PaymentId, x.TransactionId))
.ToList();
}
I am returning a result set from a stored procedure. It is one temporary table that sends back a list of integers.
When I try to return the results I get an error Generic.List<int?> to Generic.List<int>
This is what I'm trying:
using (SecurityEntities ctx = new SecurityEntities())
{
List<int> newList = ctx.spStoreSearch(storeNumber).Where(x => x != null).Select(x => x).ToList();
return test;
}
under the ctx.spStoreSearch(storeNumber).Where section it says Method, Delegate or event is expected
I based what I've currently done on this answer
Could my error be in the stored procedure itself?
This is what I'm returning from the storedProc select * from #TempTable
Select the value of Nullable int like:
.Select(x => x.Value)
You can also do casting like:
.Select(x => (int) x)
Your query could be:
List<int> newList = ctx.spStoreSearch(storeNumber)
.Where(x => x.HasValue)
.Select(x => x.Value).ToList();
You are getting the exception because your element in the List is of type int? or Nullable<int> so when you do Select(x=> x) it is selecting items of type int? and you can't assign that to List<int>.
Selects all not null values and add them into a list of integers (filtered out by using value property) .
//select int list
var nullableListIds = nullableListRecords.Select(o => o.ID).ToList();
//create list
var intList = nullableListIds.Where(n => n != null).Select(n => n.Value).ToList();
You have two options, you can either convert the nullable integers you have to 0 (or any other number that you decide to choose) and include them in your list or you can filter them out...
List<int?> nullableInts = new List<int?>();
// Lets generate some data to play with...
for (int i = 0; i < 100; i++)
{
int? digit = i % 2 == 0 ? (int?)null : i;
nullableInts.Add(digit);
}
// Below we use the GetValueOrDefault method to convert all null integers to -1
List<int> ints = nullableInts.Select(x => x.GetValueOrDefault(-1)).ToList();
// Below we simply cast the nullable integer to an integer
List<int> filteredInts = nullableInts.Where(x => x.HasValue)
.Select(x => (int)x).ToList();
I am beginner at using lambda expressions.
I have a list of dealers, foreach dealer I have to calculate grade.
The request is that the grade calculation to be separated into a separate method.
So I am writing the below two methods, however I am unable to pass parameters to CalculateGrade() method,
public IEnumerable<Dealers> GetDealerGrades(IEnumerable<Dealers> gradeData)
{
return gradeData
.GroupBy(row => new { row.Name })
.Select(g => new Dealers
{
Name = g.Key.Name,
TotalPoints = CalculateGrade(x => Convert.ToDouble(x.RecievedPoints),
y => y.MaxPoints,
z => Convert.ToDouble(z.Weightage))
})
.ToList();
}
private double CalculateGrade(double d1, int d2, double d3)
{
return ( d1 / d2 )
* d3 == 0.00 ? 1
: d3;
}
Can somebody advise how to pass parameters in this , or how to pass lamda expressions and calculate grade?
Many thanks in advance...
Looks like you need that:
return gradeData
.GroupBy(row => row.Name)
.Select(g => new Dealers
{
Name = g.Key.Name,
TotalPoints = g.Sum(x => CalculateGrade(Convert.ToDouble(x.RecievedPoints),
x.MaxPoints,
Convert.ToDouble(x.Weightage)))
})
.ToList();
It will call CalculateGrade method on every element from group and sum returned values into TotalPoints property.
Or you can change your CalculateGrade to take IEnumerabale<Dealers>:
private double CalculateGrade(IEnumerable<Dealers> dealers)
{
// calculations here
return dealers.Sum(x => CalculateGrade(Convert.ToDouble(x.RecievedPoints),
x.MaxPoints,
Convert.ToDouble(x.Weightage)))
}
And use it in your query:
return gradeData
.GroupBy(row => row.Name)
.Select(g => new Dealers
{
Name = g.Key.Name,
TotalPoints = CalculateGrade(g)
})
.ToList();
This doesn't solve your problem, but it gives you an overview how to send lambdas into methods
You would use Func & Action to pass lambdas into a method
Func
Can have 1 - 15 input parameters and must have an output parameter
Action
Can have 1 - 16 input parameters with no output parameter
ie, how I imagine they do it in EntityFramework for a where predicate
public static List<People> Filter<TEntity>(this List<People> myList, Func<TEntity, TResult> predicate)
{
return myList.Where(predicate).ToList();
}
the usage would then be something like
myList.Filter(ml => ml.Age > 18);
I have this array :
Point[] arr = samples.pointsArray;
I using this row to retrieve all elements that satisfy condition:
var maxXCol = arr.Where( p => maxX.X == p.X );
Any idea how to modify row above, to get only the indexes of these elements?
Thank you in advance!
EDIT
Use the version of Select that takes both the index and the object and create an anonymous object with the object and index inside it. It would look like this:
someEnumerable.Select((obj, idx) => new {Item = obj, Index = idx})
You'll need to do this before you use Where so that the original index remains intact after the filter operation.
In the following operations you can use the item like so:
x => x.Item
and the index like so:
x => x.Index
var maxXCol = arr.Select((p, inx) => new { p,inx})
.Where(y => maxX.X == y.p.X)
.Select(z => z.inx);
You may select the value first with the index in anonymous type, later you filter it with your condition and then select the index.
var result = arr.Select((g, index) => new { g, index })
.Where(r => maxX.X == r.X)
.Select(t => t.index);
You can use Select overload which takes an index, and project that index together with the original row. Then take only the index for the result collection.
var maxXCol = arr
.Select((p, index) => new { Item = p, Index = index })
.Where(p => maxX.X == p.Item.X)
.Select(x => x.Index);
Try this:
arr.Select((e,i)=>new{index=i, value=e}).Where(ei=>ei.value.X==maxX.X).Select(ei=>ei.index);
var maxXCol = arr
.Select((a, b) => new { b, a })
.Where(p => maxX.X == p.a.X)
.Select(i=>i.b);
Given the variable
string ids = Request.QueryString["ids"]; // "1,2,3,4,5";
Is there any way to convert it into a List without doing something like
List<int> myList = new List<int>();
foreach (string id in ids.Split(','))
{
if (int.TryParse(id))
{
myList.Add(Convert.ToInt32(id));
}
}
To create the list from scratch, use LINQ:
ids.Split(',').Select(i => int.Parse(i)).ToList();
If you already have the list object, omit the ToList() call and use AddRange:
myList.AddRange(ids.Split(',').Select(i => int.Parse(i)));
If some entries in the string may not be integers, you can use TryParse:
int temp;
var myList = ids.Split(',')
.Select(s => new { P = int.TryParse(s, out temp), I = temp })
.Where(x => x.P)
.Select(x => x.I)
.ToList();
One final (slower) method that avoids temps/TryParse but skips invalid entries is to use Regex:
var myList = Regex.Matches(ids, "[0-9]+").Cast<Match>().SelectMany(m => m.Groups.Cast<Group>()).Select(g => int.Parse(g.Value));
However, this can throw if one of your entries overflows int (999999999999).
This should do the trick:
myList.Split(',').Select(s => Convert.ToInt32(s)).ToList();
If the list may contain other data besides integers, a TryParse call should be included. See the accepted answer.
Using Linq:
myList.AddRange(ids.Split(',').Select(s => int.Parse(s));
Or directly:
var myList = ids.Split(',').Select(s => int.Parse(s));
Also, to prevent the compiler from explicitly generating the (largely redundant) lambda, consider:
var myList = ids.Split(',').Select((Func<string, int>)int.Parse);
(Hint: micro-optimization.)
There's also TryParse which should be used instead of Parse (only) if invalid input is possible and should be handled silently. However, others have posted solutions using TryParse so I certainly won't. Just bear in mind that you shouldn't duplicate the calculation.
Or including TryParse like in your example:
var res = ids.Split(',').Where(x => { int tmp; return int.TryParse(x, out tmp); }).Select(x => int.Parse(x)).ToList();
To match the request in terms of performance characteristics and behaviour, it should do the same thing and not go off doign regexes or not doing the 'TryParse':-
ds.Split(',')
.Select( i => {
int value;
bool valid = int.TryParse(out value);
return new {valid, value}
})
.Where(r=>r.valid)
.Select(r=>r.value)
.ToList();
But while correct, that's quite ugly :D
Borrowing from a hint in Jason's comment:-
ds.Split(',')
.Select( i => {
int value;
bool valid = int.TryParse(out value);
return valid ? new int?( value) : null;
})
.Where(r=>r != null)
.Select(r=>r.Value)
.ToList();
Or
static class Convert
{
public static Int32? ConvertNullable(this string s)
{
int value;
bool valid = int.TryParse(out value);
return valid ? new int?( value) : null;
}
}
ds.Split(',')
.Select( s => Convert.ConvertNullable(s))
.Where(r=>r != null)
.Select(r=>r.Value)
.ToList();
One issue at hand here is how we're gonna deal with values that are not integers (lets assume we'll get some that is not integers). One idea might be to simply use a regex:
^-?[0-9]+$
Now, we could combine all this up with (as shown in Konrad's example):
var myList = ids.Split(',').Where(s => Regex.IsMatch(s, "^-?[0-9]$")).Select(s => Convert.ToInt32(s)).ToList();
That should do the job.