Hello,
I'd like avoid loop
I have this :
string s = "AAAA,12,BBBB,34,CCCCC,56";
With Linq, I'd like to have 2 List
In the first : AAAA, BBBB and CCCCC
In the second : 12,34 and 56
It's not based on numeric or not numeric.
Thanks,
Hello,
I'd like avoid loop
I have this :
string s = "AAAA,12,BBBB,34,CCCCC,56";
With Linq, I'd like to have 2 List
In the first : AAAA, BBBB and CCCCC
In the second : 12,34 and 56
It's not based on numeric or not numeric.
Thanks,
You can use
var str = "AAAA,12,BBBB,34,CCCCC,56";
var spl = str.Split(',');
var l1 = spl.Where((x, y) => y % 2 == 0).ToList();
var l2 = spl.Where((x, y) => y % 2 == 1).ToList();
This is going to check if the index is even or odd.
There is a nice tutorial here http://msdn.microsoft.com/en-us/library/bb397915.aspx
Given that the rule is that you want every second string in one list and the others in another list, you can do something like this:
string s = "AAAA,12,BBBB,34,CCCCC,56";
var parts = s.Split(',');
var first = parts.Where((p, i) => i % 2 == 0);
var second = parts.Where((p, i) => i % 2 == 1);
I'm not sure exactly what your end goal is, but you can try this:
var strings = s.Split(',').Where( (s,p) => p % 2 == 0)
If the list is not ordered with every second being a number you could do something like this
var stringList = "AAAA,12,BBBB,34,CCCCC,56".Split(',');
var intsAsStrings = stringList.Where(
(x) =>
{
int i;
return int.TryParse(x, out i);
}).ToList();
var strings = stringList.Where(x => !intsAsStrings.Contains(x)).ToList();
Here is the isnumeric and not numeric filter for those interested... i realise its not needed
string x = "AAAA,12,BBBB,34,CCCCC,56";
Regex _isNumber = new Regex(@"^\d+$");
string[] y = x.Split(',') .Where(a => _isNumber.IsMatch(a)).ToArray();
string[] z =x.Split(',') .Where(a => !_isNumber.IsMatch(a)).ToArray();
Lets use Aggregate
for the fun of it (and also, to prove this can be done as a single expression):
"AAAA,12,BBBB,34,CCCC,56".Split(',').Aggregate(
new { Uneven = new List<string>(), Even = new List<string>() },
(seed, s) => {
if (seed.Uneven.Count > seed.Even.Count)
seed.Even.Add(s);
else
seed.Uneven.Add(s);
return seed;
});
According to LINQPad, the result is this:
Of course I probably wouldn't do it this way, as it's kind of hard to read. And the testing for which list to append to is, well, not nice.
But at least we now have another example of lambda statements - normally the LINQ literature tries to forget them (probably because they won't work with SQL or any other backend that uses expression trees).
One advantage of this method as opposed to the cleaner solutions above is that this only makes one pass through the list. Since we are splitting a string, though, I'd try optimizing somewhere else ;) Wouldn't a IEnumerable<string> Split(this string self, string boundary)
be cool?
you could group on the position and the extrat you lists from the group, like so:
public IEnumerable<IEnumerable<T>> ToLists<T>(IEnumerable<T> sequence)
{
var res = sequence.Select((item, position) => new { Item = item, Position = position })
.GroupBy(pair => pair.Position % 2 == 0,pair => pair.Item);
return from grouping in res
select grouping;
}
If you want the Lists to be of different types you can iterate through the result. Which is why the return type is not IEnumerable> but IEnumerable>. using ToList will iterate the sequence but if you want to perform some action on each element you might as well merge those actions, make one iteration through the sequnce superflourious