Giả sử tôi đã mảng sau (trình tự của tôi đều được sắp xếp theo thứ tự tăng dần, và chứa các số nguyên dương)LINQ truy vấn để xác định các mảnh vỡ trong một loạt
var mySequence = new [] {1, 2, 3, 7, 8, 9, 15, 16, 17};
Tôi muốn viết một truy vấn LINQ để chọn liên tục số trong một chuỗi được coi là một nhóm. Vì vậy, trong ví dụ trên tôi sẽ nhận được {[1, 2, 3], [7, 8, 9], [15, 16, 17]}.
Tôi có thể viết một chuỗi foreach()
, chạy qua từng phần tử và xem vị trí chuỗi đang nhảy và tạo nhóm ở đó. Nhưng có cách nào để làm điều đó không? Tôi có thể di chuyển mã số foreach()
của mình vào một phương thức mở rộng mới để mã của tôi vẫn trông LINQy, nhưng tôi tự hỏi liệu có bất kỳ điều gì có sẵn trong System.Linq đã có cho điều đó hay không.
EDIT: Tôi đã tạo tiện ích mở rộng của riêng mình (như sau), nhưng Me.Name
đã đưa ra một điều rất thông minh trong Câu trả lời của anh ấy.
internal class Sequence
{
public int Start { get; set; }
public int End { get; set; }
}
internal static class EnumerableMixins
{
public static IEnumerable<Sequence> GroupFragments(this IEnumerable<int> sequence)
{
if (sequence.Any())
{
var lastNumber = sequence.First();
var firstNumber = lastNumber;
foreach(var number in sequence.Skip(1))
{
if (Math.Abs(number - lastNumber) > 1)
{
yield return new Sequence() { Start = firstNumber, End = lastNumber };
firstNumber = lastNumber = number;
}
else
{
lastNumber = number;
}
}
yield return new Sequence() { Start = firstNumber, End = lastNumber };
}
}
}
Đây là một thủ thuật dễ thương cho integers-- nếu kết quả của (số - index) là 0 thì con số này nằm ở vị trí mảng dự kiến, nếu con số này là số âm thì nó là nhiều trước khi nó được mong đợi. – Hogan
Nếu chuỗi của tôi không bắt đầu bằng 1 thì sao? giả sử đây là chuỗi của tôi var x = new [] {20, 21, 22, 25,26,27, 30,31,32}; – fahadash
@fahadash: điều đó cũng sẽ hoạt động, ý định là sự khác biệt giữa chỉ mục và giá trị lớn hơn nếu có khoảng cách giữa các giá trị. Đối với chuỗi đó: 20-0 = 20, 21-1 = 20, 22 -2 = 20, 25 -3 = 22, 26-4 = 22, v.v. Vì vậy, giá trị 'nhóm' nhảy từ 20 đến 22 –