Dado el caso de prueba a continuación cómo puede I:eficientemente ordenar un IList <T> sin copiar la lista de fuentes
- Ordenar la
IList<TestObject>
basado en el índice de un juegoId
en la listaIList<int>
. - Los valores no coincidentes se mueven al final de la lista y se ordenan por su índice original. En este caso, dado que 3 y 4 no existen en la lista de índice, esperamos ver
list[3] == 3
ylist[4] == 4
. - Aunque sé que esto se puede lograr con linq, necesito recurrir a la lista original en lugar de crear una nueva (debido a cómo se almacena la lista).
- La lista de origen debe ser un
IList
(no puedo usarList<T>
)
Aquí está la prueba:
public class TestObject
{
public int Id { get; set; }
}
[Test]
public void Can_reorder_using_index_list()
{
IList<TestObject> list = new List<TestObject>
{
new TestObject { Id = 1 },
new TestObject { Id = 2 },
new TestObject { Id = 3 },
new TestObject { Id = 4 },
new TestObject { Id = 5 }
};
IList<int> indexList = new[] { 10, 5, 1, 9, 2 };
// TODO sort
Assert.That(list[0].Id, Is.EqualTo(5));
Assert.That(list[1].Id, Is.EqualTo(1));
Assert.That(list[2].Id, Is.EqualTo(2));
Assert.That(list[3].Id, Is.EqualTo(3));
Assert.That(list[4].Id, Is.EqualTo(4));
}
Actualización:
Conforme a lo solicitado, esto es lo que lo probé , pero 1) solo funciona con List<T>
y 2) No estoy seguro de que sea la manera más eficiente:
var clone = list.ToList();
list.Sort((x, y) =>
{
var xIndex = indexList.IndexOf(x.Id);
var yIndex = indexList.IndexOf(y.Id);
if (xIndex == -1)
{
xIndex = list.Count + clone.IndexOf(x);
}
if (yIndex == -1)
{
yIndex = list.Count + clone.IndexOf(y);
}
return xIndex.CompareTo(yIndex);
});
Actualización 2:
Gracias a @leppie, @jamiec, trigo @mitch - este es el código de trabajo:
public class TestObjectComparer : Comparer<TestObject>
{
private readonly IList<int> indexList;
private readonly Func<TestObject, int> currentIndexFunc;
private readonly int listCount;
public TestObjectComparer(IList<int> indexList, Func<TestObject, int> currentIndexFunc, int listCount)
{
this.indexList = indexList;
this.currentIndexFunc = currentIndexFunc;
this.listCount = listCount;
}
public override int Compare(TestObject x, TestObject y)
{
var xIndex = indexList.IndexOf(x.Id);
var yIndex = indexList.IndexOf(y.Id);
if (xIndex == -1)
{
xIndex = listCount + currentIndexFunc(x);
}
if (yIndex == -1)
{
yIndex = listCount + currentIndexFunc(y);
}
return xIndex.CompareTo(yIndex);
}
}
[Test]
public void Can_reorder_using_index_list()
{
IList<TestObject> list = new List<TestObject>
{
new TestObject { Id = 1 },
new TestObject { Id = 2 },
new TestObject { Id = 3 },
new TestObject { Id = 4 },
new TestObject { Id = 5 }
};
IList<int> indexList = new[] { 10, 5, 1, 9, 2, 4 };
ArrayList.Adapter((IList)list).Sort(new TestObjectComparer(indexList, x => list.IndexOf(x), list.Count));
Assert.That(list[0].Id, Is.EqualTo(5));
Assert.That(list[1].Id, Is.EqualTo(1));
Assert.That(list[2].Id, Is.EqualTo(2));
Assert.That(list[3].Id, Is.EqualTo(3));
Assert.That(list[4].Id, Is.EqualTo(4));
}
@Mitch, he actualizado mi pregunta. Lo tengo trabajando pero solo con 'List' –
@Ben - vea mi respuesta para la clasificación de su IList en el lugar, y un método de comparación potencialmente más eficiente ... ¡aunque ninguno será particularmente lento, no lo creo! – Jamiec