2010-09-23 42 views
14

xem xét việc này:IEnumerable <string> chuỗi

string test = ""; 
somestring.ToList().Take(50).Select(
    delegate(char x) 
    { 
     test += x; 
     return x; 
    } 
); 

bây giờ tại sao kiểm tra là có sản phẩm nào sau đó? tôi không quan tâm về sự trở lại của điều đó thực sự tôi biết IEnumerable của nó.

bất kỳ cách nào nếu điều này là tất cả có vẻ là một mớ hỗn độn thì làm thế nào tôi có thể chuyển đổi IEnumerable<char> thành chuỗi?

cảm ơn trước ..

Trả lời

21

Vì bạn không thực hiện truy vấn. Linq lười biếng. Nó sẽ được thực hiện khi bạn thực hiện foreach hoặc ToList/ToArray/ToDictionary.

và tôi lời khuyên để làm điều đó như thế

string test = new string(somestring.Take(50).ToArray()); 

hoặc thậm chí sử dụng

string test = somestring.Substring(0, 50); 

Thông tin thêm về đó. Select được thiết kế để áp dụng một số loại chuyển đổi cho mọi phần tử theo thứ tự. Hoạt động này còn được gọi là map. Nếu bạn muốn tạo ra phần tử đơn lẻ theo thứ tự, nó là Aggregate, còn gọi là reduce. Nó không phải là lười biếng, nó buộc thực hiện truy vấn.

+0

'Remove'? Tôi nghĩ bạn có nghĩa là 'Chuỗi con '? – Timwi

+0

@Greg Linq là khung khai báo. điều này đôi khi gây ngạc nhiên cho các nhà phát triển có đầu óc. – Andrey

+0

Điều này sẽ không biên dịch nếu 'somestring' thuộc loại 'IEnumberable '. Lớp chuỗi không có một hàm tạo quá tải lấy một mảng chuỗi. –

2

Select là lười, nên hàm bạn truyền vào sẽ chỉ được đánh giá khi bạn sử dụng kết quả của Chọn.

Thường thì ý tưởng tồi là sử dụng các hàm có tác dụng phụ với Chọn. Bạn có lẽ nên sử dụng foreach thay thế.

Trong trường hợp cụ thể này, bạn chỉ có thể sử dụng phương thức String.Join.

3

Select trả lại số IEnumerable<char> nhưng bạn không liệt kê nó trong mã của mình để đại biểu sẽ không được thực thi. Nếu bạn thay đổi nó thành:

string test = ""; 
somestring.Take(50).Select(
    delegate(char x) 
    { 
     test += x; 
     return x; 
    } 
).ToList(); 
3

Vì bạn chỉ khai báo chuỗi, nhưng bạn chưa bao giờ thực thi nó. Nếu bạn đã thêm một số khác .ToList() vào cuối thì test sẽ có các ký tự trong đó.

Tuy nhiên, tôi thực sự khuyên bạn nên chống lại thực tiễn này. Bạn đang sử dụng việc đánh giá chuỗi thành gây ra các tác dụng phụ. Bạn đã phát hiện ra rằng kết quả là khó hiểu. Nếu bạn thực sự chỉ muốn 50 hạng mục đầu tiên của một chuỗi, chỉ cần sử dụng một mình Take:

var partSequence = fullSequence.Take(50); 

ví dụ trên của bạn có thể được viết một cái gì đó như thế này:

var partString = new string(someString.Take(50).ToArray()); 

nhưng tôi chắc chắn bạn nhận thức được string.Substring() cho mục đích này.

14

(Những người khác đã giải thích lý do tại sao nó không hoạt động.)

Câu hỏi của bạn không hoàn toàn có ý nghĩa tại thời điểm này - không rõ liệu bạn đang thực sự xử lý một số IEnumerable<char> hoặc IEnumerable<string>. (Văn bản của bạn đề xuất IEnumerable<string>; mã của bạn đề xuất IEnumerable<char>). Nếu nó là một IEnumerable<string> và bạn đang sử dụng .NET 4, nó thực sự dễ dàng:

string combined = string.Join("", list.Take(50)); 

Nếu bạn đang sử dụng .NET 3.5, nó vẫn còn khá dễ dàng:

string combined = string.Join("", list.Take(50).ToArray()); 

Rõ ràng sử dụng một cái gì đó như " , "nếu bạn muốn một dấu phân tách giữa các chuỗi.

Nếu bạn đang làm việc với một vị tướng IEnumerable<char> sau đó sử dụng

string combined = new string(chars.Take(50).ToArray()); 

Nếu bạn thực sự đối phó với một chuỗi để bắt đầu, sử dụng Substring :)

+1

Vâng, nhưng tôi nghĩ anh ấy tự hỏi tại sao mã của anh ấy không hoạt động. – Timwi

+0

anh lặp qua chuỗi, xem 'delegate (char x)'. Tôi không nghĩ rằng nó là hiệu quả để làm string.Join trên ienumerable của ký tự. – Andrey

+0

@Andrey: Tôi đã căn cứ vào câu trả lời trên xác nhận rằng anh ấy đang cố gắng ghép một 'IEnumerable ', không phải là' IEnumerable ' ... về cơ bản câu hỏi đã bị hỏng vào lúc này. Tôi đã chỉnh sửa để chỉ ra điều đó. –

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