Разделить строку на список с помощью Linq

Я хотел бы избежать петли

У меня есть это :

string s = "AAAA,12,BBBB,34,CCCCC,56";

С Linq, я хотел бы иметь 2 списка

в первом : AAAA, BBBB и CCCCC

во втором : 12,34 и 56

Он не основан на числовом или не числовом.

спасибо,

8 ответов


можно использовать

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();

это проверит, является ли индекс четным или нечетным.


позволяет использовать Aggregate для удовольствия (а также, чтобы доказать, что это можно сделать в одном выражении):

"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;
    });

согласно LINQPad, результатом является следующее: alt text

конечно, я, вероятно, не сделал бы этого таким образом, так как это трудно читать. И тестирование, к которому нужно добавить список, - это, ну,не приятно.

но, по крайней мере, теперь у нас есть еще один пример лямда заявления - обычно литература LINQ пытается забудьте их (возможно, потому, что они не будут работать с SQL или любым другим бэкэндом, использующим деревья выражений).

одним из преимуществ этого метода в отличие от более чистых решений выше является то, что это делает только один проход через список. Поскольку мы разделяем строку, я бы попытался оптимизировать где-нибудь еще ;) не было бы IEnumerable<string> Split(this string self, string boundary) быть крутым?


учитывая, что правило состоит в том, что вы хотите каждую вторую строку в одном списке, а другие в другом списке, вы можете сделать что-то вроде этого:

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

Я не уверен, что именно ваша конечная цель, но вы можете попробовать это:

var strings = s.Split(',').Where( (s,p) => p % 2 == 0)

вот isnumeric, а не числовой фильтр для тех, кто заинтересован... я понимаю, что это не нужно

 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();

вы можете сгруппировать позицию и список экстратов из группы, например:

        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;
        }

Если вы хотите, чтобы списки были разных типов, вы можете повторить результат. Вот почему возвращаемый тип не IEnumerable>, а IEnumerable>. использование ToList будет повторять последовательность, но если вы хотите выполнить какое-то действие над каждым элементом, вы можете также объединить эти действия, сделайте одну итерацию через sequnce superflourious


так весело, без побочных эффектов и без вызовов методов.

"TesteDessaBudega".Aggregate(new List<List<char>>(), 
(l, c) => char.IsUpper(c) ? 
    l.Union(
        new List<List<char>>(){
            new List<char>(){c}
        }
    ).ToList() : 
    l.Take(l.Count - 1).Union(
        new List<List<char>>(){
            l.Last().Union(
                new List<char>(){c}
            ).ToList()
        }
    ).ToList() 
)

О, на vbnet просто для удовольствия.

"TesteDessaBudega".Aggregate(New List(Of List(Of Char))(), 
Function(l, c) If(Char.IsUpper(c),
    l.Union(
        New List(Of List(Of Char))(New List(Of Char)(){
            New List(Of Char)(New Char(){c})
        })
    ).ToList(),
    l.Take(l.Count - 1).Union(
        New List(Of List(Of Char))(New List(Of Char)(){
            l.Last().Union(
                New List(Of Char)(New Char(){c})
            ).ToList()
        })
    ).ToList() 
))

linqresult


Если список не упорядочен с каждой секундой находясь рядом, вы могли бы сделать что-то вроде этого

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();