将从数组A到数组B的动作排序顺序应用到数组B,重新排序

本文关键字:数组 排序 新排序 应用 顺序 | 更新日期: 2023-09-27 18:09:42

是否有可能在c#中优雅地解决以下问题?

给定两个长度相等的数组(用于存储不同的数据类型),__a和__b,

Vector3[] __a = new Vector3[]{new Vector3(0,0,2), new Vector3(0,0,1), new Vector3(0,0,4), new Vector3(0,0,3)};
int[] __b = new int[]{1, 2, 3, 4 };

如何对__a排序,同时对__b重新排序?

__a的排序可以通过System.Array.Sort()来完成,或者,例如,在LINQ的帮助下。

在对__a排序之后,在这个例子中按z坐标排序,输出如下:(0,0,1), (0,0,2), (0,0,3), (0,0,4)

并且,__b应该被重新排列成:2、1、4、3

这个问题可能看起来类似,但在我当前的情况下,数组总是具有相同的大小。它们的内容不能相互比较。相反,移动__a中的元素应该导致__b中相应元素的相同更改。

这个问题同样依赖于比较对象的内部变量。对于本例,我使用了Vector3和int数据类型,然而,实际上__B可以携带对自定义对象的引用,并且不能进行比较。

是否有一种方法来"扩展"Array.Sort(),以便当__a被重新排列时,__b以完全相同的方式重新排列?也许有一种方法来使用LINQ?

将从数组A到数组B的动作排序顺序应用到数组B,重新排序

Array.Sort有一个特定的过载。

使用指定的IComparer<T>泛型接口,根据第一个Array中的键对一对Array对象(一个包含键,另一个包含相应的项)进行排序。

您将需要为您的键编写这样一个IComparer<T>接口,这取决于您想使用哪个矢量组件来比较它们。下面是一个示例,假设您的第三个组件是Z:

class ThirdComponentComparer : IComparer<Vector3>
{
    public int Comparer(Vector3 a, Vector3 b)
    {
        // Null checks first?
        return a.Z.CompareTo(b.Z);
    }
}
Array.Sort(__a, __b, new ThirdComponentComparer());

这有点做作,但是可以工作:

int[] a =  { 1, 2, 3, 4 };
double[] d = { 2.0, 1.0, 4.0, 3.0 };
var sortedIntArray = d.Select((elem, index) => new { Value = elem, Index = index })
                      .OrderBy(n => n.Value)
                      .Zip(a, (first, second) => new { first, second })
                      .OrderBy(x => x.first.Index)
                      .Select(x => x.second)
                      .ToArray();

您也可以通过两个步骤来完成。Sort __a,保持项目的原始索引排序。然后使用这些索引重新排序__b:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
    class Program
    {
        internal class Foo {
            public int Index { get; set; }
            public Foo(int index)
            {
                this.Index = index;
            }
        }
        internal class Bar {
            public string Text { get; set; }
            public Bar(string text)
            {
                this.Text = text;
            }
        }
        static void Main(string[] args)
        {
            Foo[] __a = new[] { new Foo(4), new Foo(3), new Foo(2), new Foo(1), new Foo(0) };
            Bar[] __b = new[] { new Bar("Y"), new Bar("Z"), new Bar("Z"), new Bar("Y"), new Bar("X") };
            // Sort all foos, by Value, keeping the original index.
            var sorted = __a.Select((x, i) => new KeyValuePair<Foo, int>(x, i)).OrderBy(x => x.Key.Index);
            // Retrieve the sorted foos as a Foo[].
            var sortedFoos = sorted.Select(x => x.Key).ToArray();
            // Pick the bars according to the original index of the foos.
            var sortedBars = sorted.Select(x => __b[x.Value]).ToArray();
            Console.WriteLine(string.Concat(sortedFoos.Select(x => x.Index)));
            Console.WriteLine(string.Concat(sortedBars.Select(x => x.Text)));
        }
    }
}

01234
XYZZY
Press any key to continue . . .