No importa cómo lo intente, me parece que no puede crear un bonito y limpio, el algoritmo de la siguiente manera:

  1. Sistema.Array (genérico o de Lista) datos de Sistema.Objeto
  2. Sistema.Array (genérico o de Lista) xval de Sistema.Objeto
  3. Sistema.Array (genérico o de Lista) idxs de Sistema.Int32

xval y idxs contienen el mismo número de elementos y idxs no contiene un valor menor que cero o mayor que de datos.Longitud

Necesito para insertar todos los elementos en xval en el datos matriz, donde los asociados entero en idxs representa el índice de inserción en el original, sin ser molestados datos.

Por ejemplo:

*data* = {A, B, C, D, E, F, G, H}
*xval* = {U, V, W, X, Y, Z}
*idxs* = {5, 0, 0, 0, 1, 1}

*output* = {V, W, X, A, Y, Z, B, C, D, E, U, F, G, H}

Es bastante fácil de hacer, pero siempre termino con icky código. Mi mejor intento hasta la fecha (pero estoy preocupada acerca de errores de redondeo):

  idxs.Reverse()
  xval.Reverse()

  Dim N As Int32 = data.Count + xval.Count
  Dim map(N - 1) As Double
  Dim output(N - 1) As Object

  Dim k As Int32 = -1
  For i As Int32 = 0 To data.Count - 1
    k += 1
    map(k) = i
    output(k) = data(i)
  Next
  For i As Int32 = 0 To xval.Count - 1
    k += 1
    map(k) = idxs(i) - ((i + 1) * 1e-8)
    output(k) = xval(i)
  Next

  Array.Sort(map, output)
InformationsquelleAutor David Rutten | 2010-09-10

4 Comentarios

  1. 4

    Aquí está mi intento, que no utiliza IndexOf, Sort, Reverse, diccionarios, o dobles.

    //input data
    char[] data = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
    char[] xval = { 'U', 'V', 'W', 'X', 'Y', 'Z' };
    int[] idxs = { 5, 0, 0, 0, 1, 1 };
    
    //algorithm starts here
    var output = new List<char>(data);
    for (int i = 0; i < idxs.Length; i++)
    {
        //Insert the i’th item in the right place
        output.Insert(idxs[i], xval[i]);
    
        //Increment all the following indexes so that they
        //will insert in the right place
        for (int j = i + 1; j < idxs.Length; j++)
            if (idxs[j] >= idxs[i])
                idxs[j]++;
    }
    
    //outputs V, W, X, A, Y, Z, B, C, D, E, U, F, G, H
    Console.WriteLine(string.Join(", ", output));

    Por supuesto, si usted no desea que el algoritmo para modificar el idxs matriz, entonces simplemente hacer una copia de ella en primer lugar.

    • No puede conseguir mucho más claro que esto, en mi opinión. (Aunque en lugar de incrementar los números en la idxs matriz, me gustaría mantener un entero contador de cómo muchas inserciones he hecho y añade que a cada uno de los índices como me fui.)
    • Me encantaría ver tu código para que, porque no veo cómo se puede hacer eso. Quiero pegar en pastebin.com y enviar el enlace aquí en un comentario?
    • Sí, esto es casi exactamente lo que yo estaba buscando. Gracias!
    • Ah, lo siento por eso. Que mal pensado; su solución es, sin duda la más clara.
  2. 1

    Yo iría a por algo como esto (reemplazar ‘char’ con ‘objeto’)

    char[] data = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
    char[] xval = new char[] { 'U', 'V', 'W', 'X', 'Y', 'Z' };
    int[] idxs = new int[] { 5, 0, 0, 0, 1, 1 };
    List<char> output = data.ToList();
    
    Dictionary<int, List<char>> dict = new Dictionary<int, List<char>>();
    for (int i = 0; i < idxs.Length; i++)
    {
        if (!dict.ContainsKey(idxs[i]))
            dict.Add(idxs[i], new List<char>());
        dict[idxs[i]].Add(xval[i]);
    }
    List<int> keys = dict.Keys.ToList();
    keys.Sort();
    keys.Reverse();
    foreach (int key in keys)
        output.InsertRange(key,dict[key]);
    • Inteligente. No marcado como respuesta, todavía en una vana esperanza de que alguien viene con una solución más pequeña todavía.
  3. 1
    '*data* = {A, B, C, D, E, F, G, H}
    '*xval* = {U, V, W, X, Y, Z}
    '*idxs* = {5, 0, 0, 0, 1, 1}
    '*output* = {V, W, X, A, Y, Z, B, C, D, E, U, F, G, H}
        Dim data As New List(Of String)
        Dim xval As New List(Of String)
        Dim idxs As New List(Of Integer)
        Dim output As New List(Of String)
    
        data.AddRange(New String() {"A", "B", "C", "D", "E", "F", "G", "H"})
        xval.AddRange(New String() {"U", "V", "W", "X", "Y", "Z"})
        idxs.AddRange(New Integer() {5, 0, 0, 0, 1, 1})
    
        For x As Integer = 0 To data.Count - 1 'for each item in the data
            Dim idx As Integer = idxs.IndexOf(x)
            Do While idx <> -1 'do we have xval's for this index
                output.Add(xval(idx)) 'yes add it
                xval.RemoveAt(idx) 'remove the items from xval
                idxs.RemoveAt(idx) 'and idxs
                idx = idxs.IndexOf(x)
            Loop
            output.Add(data(x)) 'add data item to list
        Next
    • Solución inteligente.
    • Gracias. Trato de mantener este tipo de cosas tan simples como sea posible.
    • Una conjetura sería que Timwi la solución sería mucho más rápido.
  4. 0

    Nota que no hay inversión de las listas.

        IList<Object> data = new Object[] { "A", "B", "C", "D", "E", "F", "G", "H" };
        IList<Object> xval = new Object[] { "U", "V", "W", "X", "Y", "Z" };
        IList<int> idxs = new int[] { 5, 0, 0, 0, 1, 1 };
    
        List<Object> output = new List<object>(data);
    
        for (int i = 0; i < xval.Count; i++)
        {
            int currentIndex = idxs[i];
            Object dataElement= data[currentIndex]; //We should insert the new element before this element.
            int elementsIndex = output.IndexOf(dataElement);
            output.Insert(elementsIndex, xval[i]);
        }
        return output;
    • Jeroen, buen intento, pero IndexOf no puede ser de confianza. La lista puede contener el mismo objeto varias veces o puede contener varios valores nulos.
    • En caso de que la respuesta de Timwi es el que tiene que ir en este momento.

Dejar respuesta

Please enter your comment!
Please enter your name here