2009-01-04 20 views
11

F # có một loạt các toán tử chuỗi chuẩn mà tôi đã biết và yêu thích từ trải nghiệm của tôi với Mathematica. F # đang nhận được rất nhiều sự chú ý của tôi bây giờ, và khi nó được phát hành chung, tôi có ý định sử dụng nó thường xuyên.F # Mô-đun Seq được triển khai trong C# cho IEnumerable?

Ngay bây giờ, vì F # chưa được phát hành chung, tôi thực sự không thể sử dụng nó trong mã sản xuất. LINQ thực hiện một số toán tử bằng cách sử dụng tên giống SQL (ví dụ: 'chọn' là 'bản đồ' và 'ở đâu' là 'bộ lọc'), nhưng tôi không thể thực hiện 'gấp', 'lặp lại' hoặc 'phân vùng'.

Có ai nhìn thấy bất kỳ triển khai C# nào của nhà khai thác chuỗi tiêu chuẩn không? Đây có phải là điều mà ai đó nên viết không?

Trả lời

6
  • lần = Aggregate

biết chính xác những gì sử dụng iterpartition làm, và chúng ta có thể điền vào chỗ trống. Tôi đoán iter = SelectMany và phân vùng có thể liên quan đến Skip/Take?


(cập nhật) Tôi nhìn lên Partition - đây là một thực thô mà một số của nó:

using System; 
using System.Collections.Generic; 
static class Program { // formatted for space 
    // usage 
    static void Main() { 
     int[] data = { 1, 2, 3, 4, 5, 6 }; 
     var qry = data.Partition(2); 

     foreach (var grp in qry) { 
      Console.WriteLine("---"); 
      foreach (var item in grp) { 
       Console.WriteLine(item); 
      } 
     } 
    } 

    static IEnumerable<IEnumerable<T>> Partition<T>(
      this IEnumerable<T> source, int size) { 

     int count = 0; 
     T[] group = null; // use arrays as buffer 
     foreach (T item in source) { 
      if (group == null) group = new T[size]; 
      group[count++] = item; 
      if (count == size) { 
       yield return group; 
       group = null; 
       count = 0; 
      } 
     } 
     if (count > 0) { 
      Array.Resize(ref group, count); 
      yield return group; 
     } 
    } 
} 
1

iter tồn tại như một phương thức trong lớp Danh sách đó là ForEach

khác:

public static void iter<T>(this IEnumerable<T> source, Action<T> act) 
     { 
      foreach (var item in source) 
      { 
       act(item);     
      } 
     } 
0

Di chuyển của riêng bạn trong C# là một bài tập thú vị, ở đây là af ew của tôi. (Xem thêm here)

Lưu ý rằng iter/foreach trên IEnumerable hơi gây tranh cãi - tôi nghĩ vì bạn phải 'hoàn thành' (hoặc bất kỳ từ nào) IEnumerable để bất cứ điều gì thực sự xảy ra.

//mimic fsharp map function (it's select in c#) 
    public static IEnumerable<TResult> Map<T, TResult>(this IEnumerable<T> input, Func<T, TResult> func) 
    { 
     foreach (T val in input) 
      yield return func(val); 
    } 

    //mimic fsharp mapi function (doens't exist in C#, I think) 
    public static IEnumerable<TResult> MapI<T, TResult>(this IEnumerable<T> input, Func<int, T, TResult> func) 
    { 
     int i = 0; 
     foreach (T val in input) 
     { 
      yield return func(i, val); 
      i++; 
     } 
    } 

    //mimic fsharp fold function (it's Aggregate in c#) 
    public static TResult Fold<T, TResult>(this IEnumerable<T> input, Func<T, TResult, TResult> func, TResult seed) 
    { 
     TResult ret = seed; 
     foreach (T val in input) 
      ret = func(val, ret); 
     return ret; 
    } 

    //mimic fsharp foldi function (doens't exist in C#, I think) 
    public static TResult FoldI<T, TResult>(this IEnumerable<T> input, Func<int, T, TResult, TResult> func, TResult seed) 
    { 
     int i = 0; 
     TResult ret = seed; 
     foreach (T val in input) 
     { 
      ret = func(i, val, ret); 
      i++; 
     } 
     return ret; 
    } 

    //mimic fsharp iter function 
    public static void Iter<T>(this IEnumerable<T> input, Action<T> action) 
    { 
     input.ToList().ForEach(action); 
    } 
+2

Tương đương mapi tồn tại dưới dạng quá tải Chọn. Ngoài ra, có vẻ hơi nặng để chuyển đổi danh sách của bạn thành danh sách thay vì thực hiện vòng lặp foreach bình thường và gọi hành động mỗi lần ... –

+0

Không biết về Chọn quá tải, cảm ơn vì điều đó. ToList là điều đầu tiên tôi nghĩ đến, tôi đoán vậy. – Benjol

14

Nếu bạn xem kỹ, nhiều hoạt động Seq có LINQ tương đương hoặc có thể dễ dàng bắt nguồn. Chỉ cần nhìn xuống list ...

  • Seq.append = Concat<TSource>(IEnumerable<TSource> second)

  • Seq.concat = SelectMany<IEnumerable<TSource>, TResult>(s => s)

  • Seq.distinct_by = GroupBy(keySelector).Select(g => g.First())

  • Seq.exists = Any<TSource>(Func<TSource, bool> predicate)

  • Seq.mapi = Select<TSource, TResult>(Func<TSource, Int32, TResult> selector)

  • Seq.fold = Aggregate<TSource, TAccumulate>(TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func)

List.partition được định nghĩa như thế này:

Chia bộ sưu tập thành hai bộ sưu tập, có chứa các yếu tố mà các vị trao trả truefalse tương ứng

nào chúng ta có thể triển khai thực hiện bằng GroupBy và một mảng hai phần tử như một bộ phận của người nghèo:

public static IEnumerable<TSource>[] Partition<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
{ 
    return source.GroupBy(predicate).OrderByDescending(g => g.Key).ToArray(); 
} 

Phần tử 0 giữ giá trị thực; 1 giữ giá trị sai. GroupBy về cơ bản là phân vùng trên steroid.

Và cuối cùng, Seq.iterSeq.iteri bản đồ một cách dễ dàng để foreach:

public static void Iter<TSource>(this IEnumerable<TSource> source, Action<TSource> action) 
{ 
    foreach (var item in source) 
     action(item); 
} 

public static void IterI<TSource>(this IEnumerable<TSource> source, Action<Int32, TSource> action) 
{ 
    int i = 0; 
    foreach (var item in source) 
     action(i++, item); 
} 
+0

Vấn đề với 'phân vùng' của bạn khi tất cả các phần tử khớp hoặc tất cả đều không thành công: bạn nhận được một mảng đơn. Vui lòng xem [câu trả lời của tôi] (http://stackoverflow.com/a/8931453/97846), lấy cảm hứng từ bạn. –

1

ToLookup lẽ sẽ là một trận đấu tốt hơn cho List.partition:

IEnumerable<T> sequence = SomeSequence(); 
ILookup<bool, T> lookup = sequence.ToLookup(x => SomeCondition(x)); 
IEnumerable<T> trueValues = lookup[true]; 
IEnumerable<T> falseValues = lookup[false]; 
+0

... ngoại trừ việc nó không phải là lười biếng. –

0

Dưới đây là một bản cập nhật để dahlbyk'spartition giải pháp.

Nó trả về một array[] trong đó "phần tử 0 giữ giá trị đúng; 1 giữ giá trị false" — nhưng điều này không giữ khi tất cả các phần tử khớp hoặc không thành công. mảng và một thế giới của đau đớn.

public static Tuple<IEnumerable<T>, IEnumerable<T>> Partition<T>(this IEnumerable<T> source, Func<T, bool> predicate) 
{ 
    var partition = source.GroupBy(predicate); 
    IEnumerable<T> matches = partition.FirstOrDefault(g => g.Key) ?? Enumerable.Empty<T>(); 
    IEnumerable<T> rejects = partition.FirstOrDefault(g => !g.Key) ?? Enumerable.Empty<T>(); 
    return Tuple.Create(matches, rejects); 
} 
Các vấn đề liên quan