Reputation: 317
I have another question which is related to this: Filter an IEnumerable in Linq with an array. But after this I got a new requirement like,
having an array string[] BranchIds = {"1","2","3"}
var a =_abc.GetRoutes(0)
.Where(r => BranchIds.Contains(r.StringBranchIds))
.ToList();
What if the StringBranchIds
in this code is also a comma separated string?
I have tried some thing like:
var a =_abc.GetRoutes(0)
.Where(n => BranchIds.Contains((n.StringBranchIds.Replace(" ", "")
.Split(',')
.Select(m => Convert.ToInt32(m))
.ToArray()).ToString()));
but no go.
Here inside Contains
I'm able to give only strings. Is the Linq works like that?
I'm pretty new to Linq, please gimme a hand!
Upvotes: 0
Views: 6424
Reputation: 1062600
The Contains
method asks whether a single value is in a wider sequence/list. You don't have that; you have (for each branch):
StringBranchIds
against the "route", which we can relatively easily convert to a flat listBranchIds
that is the fixed list we're testing againstThis is nothing to do with contains.
Assuming you mean "any intersection", then this would be something like:
var a =_abc.GetRoutes(0).Where(n =>
n.StringBranchIds.Replace(" ", "").Split(',').Any(
id => BranchIds.Contains(id)
));
What this does is:
StringBranchIds
into piecesBranchIds
Note, however, that this is not optimal in terms of performance - lots of O(N)
testing. If BranchIds
is relatively small, you'll probably be fine (any O(1)
"improvements" will probably be slower than the O(N)
, for small N
). If BranchIds
is long, you could pre-process it into a HashSet<string>
, etc.
Note that I haven't parsed anything to int
- there's no need to, and that won't help your performance.
Additionally, you should think about would be pre-processing the StringBranchIds
into something amenable to testing; this doesn't necessarily involve many changes. For example, from here:
public string StringBranchIds {get;set;}
we can change to:
private string _stringBranchIds;
public string StringBranchIds {
get { return _stringBranchIds; }
set {
if(value != _stringBranchIds) {
_stringBranchIds = value;
_splitIds = null; // only if actually a change
}
}
}
private string _splitIds;
internal string[] GetSplitIds() {
return _splitIds ?? (_splitIds =
(_stringBranchIds ?? "").Replace(" ", "").Split(','));
}
Now we just change our method to use n.GetSplitIds()
instead of n.StringBranchIds
, and it will get back the same array of ids until the value is changed. Much cheaper than splitting it each time.
Upvotes: 2
Reputation: 9365
With you split logic
var a =_abc.GetRoutes(0).Where(r =>
!r.StringBranchIds.Replace(" ", "").Split(',').Except(BranchIds).Any()).ToList();
This will get back only the routes that have all of their StringBranchIds
contained within the BranchIds
.
Upvotes: 0