2010-09-29 31 views
10

Tôi muốn tránh lặpChia chuỗi vào danh sách <string> với LINQ

Tôi có điều này:

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

Với LINQ, tôi muốn có 2 Danh sách

Trong lần đầu tiên: AAAA, BBBB và CCCCC

Trong giây: 12,34 và 56

Nó không dựa trên num eric hoặc không phải là số.

Cảm ơn,

+1

gì là phân vùng của chuỗi dựa trên? Vị trí trong danh sách, số ký tự, v.v ...? –

+0

Có vị trí trong danh sách –

+2

'Tôi muốn tránh vòng lặp' Bạn nhận ra rằng bất kỳ giải pháp LINQ nào bạn quyết định sẽ thực tế, sử dụng ít nhất một vòng lặp? –

Trả lời

29

Bạn có thể sử dụng

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

này sẽ kiểm tra xem chỉ số là chẵn hoặc lẻ.

1

Có một hướng dẫn tốt đẹp ở đây http://msdn.microsoft.com/en-us/library/bb397915.aspx

+0

Trong khi liên kết này có thể trả lời câu hỏi, tốt hơn nên bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo. Câu trả lời chỉ liên kết có thể trở thành không hợp lệ nếu trang được liên kết thay đổi. - [Từ đánh giá] (/ review/low-quality-posts/18997612) –

6

Cho rằng các quy tắc là bạn muốn mọi chuỗi thứ hai trong một danh sách và những người khác trong danh sách khác, bạn có thể làm một cái gì đó như thế này:

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

tôi không chắc chắn chính xác những gì mục tiêu cuối cùng của bạn, nhưng bạn có thể thử điều này:

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

Nếu danh sách không đặt mua với mỗi thứ hai là một số bạn có thể làm somethin g như thế này

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

Tại sao không chỉ đơn giản là sử dụng Ngoại trừ thay vì ở đó (x =>! IntsAsStrings.Contains (x))? Ngoài ra đây không phải là những gì tác giả của câu hỏi muốn. – sloth

+0

Không biết phương pháp Ngoại trừ, tốt đẹp. – Xorandor

1

Dưới đây là bộ lọc IsNumeric và không số cho những người quan tâm ... tôi nhận ra mình không cần thiết

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

Cho phép sử dụng Aggregate cho những niềm vui của nó (và cũng để chứng minh điều này có thể được thực hiện như một biểu hiện duy nhất):

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

Theo LINQPad, kết quả là thế này: alt text

Tất nhiên tôi có lẽ sẽ không làm theo cách này, vì nó rất khó đọc. Và thử nghiệm cho danh sách để thêm vào là, tốt, không đẹp.

Nhưng ít nhất chúng ta có một ví dụ khác là báo cáo lambda - thông thường tài liệu LINQ cố gắng quên chúng (có thể vì chúng sẽ không hoạt động với SQL hoặc bất kỳ chương trình phụ trợ nào khác sử dụng cây biểu thức).

Một lợi thế của phương pháp này trái ngược với các giải pháp làm sạch ở trên là điều này chỉ làm cho một người vượt qua danh sách. Vì chúng tôi đang tách một chuỗi, mặc dù, tôi sẽ cố gắng tối ưu hóa ở một nơi khác;) Sẽ không phải là IEnumerable<string> Split(this string self, string boundary) được mát mẻ?

+0

Eh, tuyệt. Khó thực tế nhưng thật tuyệt. –

+0

Bằng cách nào đó nó có vẻ giống như một sự lạm dụng kỳ lạ của 'Tổng hợp' nếu hàm tích lũy sửa đổi tham số nguồn. Nó cảm thấy như sau lá thư của lập trình chức năng trong khi mâu thuẫn với tinh thần. Tôi có phải là người duy nhất nghĩ vậy không? – Niki

+0

@nikie với "tham số nguồn" bạn có nghĩa là 'TSource' (không được sửa đổi) hoặc' TAccumulate' (đã sửa đổi, nhưng không phải luôn luôn như vậy?) –

1

bạn có thể nhóm vào vị trí và trích xuất danh sách bạn khỏi nhóm, như vậy:

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

Nếu bạn muốn Chức năng để được các loại khác nhau mà bạn có thể lặp qua kết quả. Đó là lý do tại sao loại trả về không phải là IEnumerable> nhưng IEnumerable>. việc sử dụng ToList sẽ lặp lại chuỗi nhưng nếu bạn muốn thực hiện một số hành động trên mỗi phần tử, bạn có thể hợp nhất các hành động đó, thực hiện một lần lặp lại thông qua sequnce superflourious

0

Rất nhiều niềm vui, không có tác dụng phụ và không có cuộc gọi phương thức.

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

Ồ, trên vbnet chỉ để vui hơn.

"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

+1

Thực sự không chắc chắn về cách thức này có bất kỳ sự liên quan nào đến câu hỏi. Tôi có cảm giác bạn đang trả lời một câu hỏi khác. – btlog

Các vấn đề liên quan