将从数组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?
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 . . .