根据另一个数组中指定的索引从数组中选择元素(C#)

11

假设我们有一个带数据的数组:

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

一个大小为N的数组,其中包含与x的元素相对应的标签:

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

如何最快地选择所有带有特定标签I的元素从x中,根据ind

例如,

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

结果:

y = {3, 6, 2}

显然,使用循环可以轻松地完成这项任务(但不够高效和简洁),但我认为应该有一种使用.Where和lambda表达式的方法..谢谢。

编辑:

MarcinJuraszek提供的答案是完全正确的,谢谢。然而,如果我们有通用类型,您能否看看问题所在:

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

使用提供的解决方案时,我收到一个错误提示:"委托 'System.Func' 不接受 2 个参数":

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

非常感谢。

2个回答

18

那怎么样:

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

它使用第二种较不流行的重载Where

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

该方法还将项索引作为谓词参数(在我的解决方案中称为idx)。

通用版本

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

用法

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

通用+double版本

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

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

非常好,谢谢。你能否请看一下编辑过的问题版本? - Oleg Shirokikh
1
对于泛型,您必须确保定义了 T2 == T2(或 T2.Equals(T2))- 添加泛型约束 where T2 : IEquatable - MarcinJuraszek
你能建议一下我应该如何添加这个限制条件吗? - Oleg Shirokikh
谢谢。很抱歉,但我遇到了一个错误。如果xsT1indT2resultsT2,它会说“类型T2不能用作类型参数...没有从T2到System.IEquatable<T2>的装箱转换或类型参数转换”。我知道我做错了什么,你的回答很好。如果您能帮忙,我将不胜感激。 - Oleg Shirokikh
你正在使用的类 T2 没有实现 IEquatable<> 接口。请实现它,然后它就可以工作了。 - MarcinJuraszek
显示剩余2条评论

5
这是 Enumerable.Zip 的典型用法,它可以同时遍历两个可枚举对象。使用 Zip 可以一次性获取结果。下面的示例代码是完全不依赖类型的,但我使用 int 和 string 来说明:
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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接