【问题标题】:Selecting elements from array according to indices specified in another array c#根据另一个数组c#中指定的索引从数组中选择元素
【发布时间】:2013-04-03 19:07:24
【问题描述】:

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

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

以及大小为N的数组,包含与x的元素对应的标签:

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

根据indx中选择具有特定标签I的所有元素的最快方法是什么?

例如,

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

结果:

y = {3, 6, 2}

显然,使用循环可以轻松(但不是高效和清洁)完成,但我认为应该有使用.Where 和 lambdas 的方法。谢谢

编辑:

MarcinJuraszek 提供的答案是完全正确的,谢谢。但是,我已经简化了这个问题,希望它能在我原来的情况下工作。如果我们有泛型类型,您能否看看有什么问题:

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

使用提供的解决方案我收到错误“Delegate 'System.Func' does not take 2 arguments”:

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

非常感谢

【问题讨论】:

    标签: c# arrays linq select lambda


    【解决方案1】:

    怎么样:

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

    【讨论】:

    • 非常好,谢谢。你能看看问题的编辑版本吗?
    • 对于泛型,您必须确保已定义 T2 == T2(或 T2.Equals(T2)) - 添加泛型约束 where T2 : IEquatable
    • 你能建议我应该如何加入这个约束吗?
    • 谢谢。我很抱歉,但我遇到了一个错误。如果xsT1indT2resultsT2 它说“T2 类型不能用作类型参数...没有装箱转换或类型参数从 T2 转换为System.IEquatable”。我知道我做错了什么,你的回答很好。如果可以的话,我将不胜感激
    • 您作为T2 使用的类没有实现IEquatable&lt;&gt;。实施它,它会起作用的。
    【解决方案2】:

    这是Enumerable.Zip 的经典用法,它贯穿两个相互平行的枚举。使用 Zip,您可以一次性获得结果。以下内容完全与类型无关,尽管我使用 ints 和 strings 进行说明:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-14
      • 2012-07-19
      • 1970-01-01
      • 1970-01-01
      • 2018-12-24
      • 1970-01-01
      相关资源
      最近更新 更多