2013-04-03 29 views
7

Giả sử chúng ta có một mảng với dữ liệu:yếu tố Lựa chọn từ mảng theo chỉ số quy định trong một mảng C#

double[] x = new double[N] {x_1, ..., x_N}; 

Và mảng có kích thước N chứa nhãn tương ứng với các yếu tố của x:

int[] ind = new int[N] {i_1, ..., i_N}; 

Cách nhanh nhất để chọn tất cả các yếu tố từ x có nhãn nhất định I theo ind là gì?

Ví dụ,

x = {3, 2, 6, 2, 5} 
ind = {1, 2, 1, 1, 2} 
I = ind[0] = 1 

Kết quả:

y = {3, 6, 2} 

Rõ ràng, nó có thể được dễ dàng (nhưng không có hiệu quả và sạch sẽ) thực hiện với các vòng, nhưng tôi nghĩ rằng cần có cách làm thế nào để làm điều đó bằng .Where và lambdas..Thanks

EDIT:

Câu trả lời được cung cấp bởi MarcinJuraszek là hoàn toàn chính xác, cảm ơn. Tuy nhiên, tôi đã đơn giản hóa câu hỏi với hy vọng rằng nó sẽ hoạt động trong tình huống ban đầu của tôi. bạn có thể xin hãy xem vấn đề là gì nếu chúng ta có các loại generic:

T1[] xn = new T1[N] {x_1, ..., x_N}; 
T2[] ind = new T2[N] {i_1, ..., i_N}; 
T2 I = ind[0] 

Sử dụng các giải pháp cung cấp tôi nhận được một lỗi "Delegate 'System.Func' không mất 2 đối số":

T1[] y = xn.Where((x, idx) => ind[idx] == I).ToArray(); 

Thank you very much

Trả lời

14

Làm thế nào về điều đó:

var xs = new[] { 3, 2, 6, 2, 5 }; 
var ind = new[] { 1, 2, 1, 1, 2 }; 
var I = 1; 

var results = xs.Where((x, idx) => ind[idx] == I).ToArray(); 

Nó sử dụng thứ hai, ít phổ biến, Where quá tải:

Enumerable.Where<TSource>(IEnumerable<TSource>, Func<TSource, Int32, Boolean>)

trong đó có chỉ số mục có sẵn như là tham số vị ngữ (gọi tắt là idx trong dung dịch của tôi).

phiên bản Generic

public static T1[] WhereCorresponding<T1, T2>(T1[] xs, T2[] ind) where T2 : IEquatable<T2> 
{ 
    T2 I = ind[0]; 
    return xs.Where((x, idx) => ind[idx].Equals(I)).ToArray(); 
} 

Cách sử dụng

static void Main(string[] args) 
{ 
    var xs = new[] { 3, 2, 6, 2, 5 }; 
    var ind = new[] { 1, 2, 1, 1, 2 }; 

    var results = WhereCorresponding(xs, ind); 
} 

Generic + double phiên bản

public static T[] Test<T>(T[] xs, double[] ind) 
{ 
    double I = ind[0]; 

    return xs.Where((x, idx) => ind[idx] == I).ToArray(); 
} 
+0

Đã suy nghĩ về việc sử dụng Zip, nhưng quái: ngắn hơn thế này nó không phải là gonna get .. – flq

+0

Nó là rất tốt đẹp , cảm ơn. Bạn có thể xem phiên bản câu hỏi đã chỉnh sửa không? –

+1

Đối với generics, bạn phải chắc chắn 'T2 == T2' (hoặc' T2.Equals (T2) ') được xác định - thêm ràng buộc chung' nơi T2: IEquatable' – MarcinJuraszek

4

Đây là một ứng dụng cổ điển cho Enumerable.Zip, chạy qua hai số đếm song song với nhau. Sử dụng Zip bạn có thể nhận được kết quả của bạn với một lần.Sau đây là hoàn toàn gõ-agnostic, mặc dù tôi sử dụng int s và string s mang tính minh họa:

int[] values = { 3, 2, 6, 2, 5 }; 
string[] labels = { "A", "B", "A", "A", "B" }; 
var searchLabel = "A"; 

var results = labels.Zip(values, (label, value) => new { label, value }) 
        .Where(x => x.label == searchLabel) 
        .Select(x => x.value); 
Các vấn đề liên quan