Sribin
Sribin

Reputation: 317

How to do a Linq on a comma separated string

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

Answers (2)

Marc Gravell
Marc Gravell

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):

  • a StringBranchIds against the "route", which we can relatively easily convert to a flat list
  • a BranchIds that is the fixed list we're testing against

This 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:

  • split the StringBranchIds into pieces
  • for each of these, test whether it is contained in BranchIds

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

Ofir Winegarten
Ofir Winegarten

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

Related Questions