Tengo una Lista con los números, me gustaría encontrar la posición del mínimo (no el valor), utilizando LINQ

por ejemplo: {3,1,0,5}
salida = 2

  • son los valores que siempre va a ser distinto?
  • no, los valores no son únicos
  • Hmmm, si los valores no son únicos, entonces supongo que uno podría querer encontrar múltiples posiciones. O la posición del primer mínimo valor encontrado.
  • Si en cambio usted quería una colección de valores únicos, entonces usted querrá considerar el uso de una colección de la clase que hereda de ISet<T>: que es HashSet<T> o SortedSet<T>.
InformationsquelleAutor | 2009-07-10

9 Comentarios

  1. 74
    var list = new List<int> { 3, 1, 0, 5 };
    int pos = list.IndexOf(list.Min()); //returns 2
    • ¿Qué sucede si hay otro elemento en la lista que también es 0? No estoy criticando, sólo quiero saber.
    • la lista de objetos genéricos de seguir la pista de los valores min en ellos?
    • Devuelve el primer índice de los mínimos
    • Creo que IndexOf devuelve el primer índice del parámetro especificado, o -1 si no se encontró.
    • (Porcentaje) se Busca el objeto especificado y devuelve el índice de base cero de la primera aparición dentro de la Lista completa<(De < T>)>). msdn.microsoft.com/en-us/library/e4w08k17.aspx
  2. 40

    Como usted se lo haya pedido una LINQ solución, y todo lo que obtuve fue que no LINQ soluciones, he aquí una LINQ solución:

    List<int> values = new List<int> { 3, 1, 0, 5 };
    
    int index =
       values
       .Select((n, i) => new { Value = n, Index = i })
       .OrderBy(n=>n.Value)
       .First()
       .Index;

    Que sin embargo no significa que LINQ es la mejor solución para este problema…

    Edit:

    Con un poco más complejo de este código realiza un poco mejor:

    int index =
       values
       .Select((n, i) => new { Value = n, Index = i })
       .Aggregate((a,b) => a.Value < b.Value ? a : b)
       .Index;

    Para obtener el mejor rendimiento, utilice un simple bucle de ir a buscar a través de los elementos, mientras que usted guarde la pista de los más bajos:

    int index = 0, value = values[0];
    for (int i = 1; i < values.Length; i++) {
      if (values[i] < value) {
        value = values[i];
        index = i;
      }
    }
    • Técnicamente alguien añadido el requisito de LINQ
    • En realidad, parece que el cartel original etiquetado se LINQ, pero no mencionó LINQ en el post.
    • ¿Por qué el downvote? Si no explique lo que usted piensa que está mal, no puede mejorar la respuesta.
    • ¿Usted tiene una mejor sugerencia sobre cómo hacer que el uso de LINQ?
    • usted podría utilizar agregado (como shoelzer de la respuesta), o caer de nuevo en la escritura de un método de extensión. Su solución funciona y es legible, pero hace un trabajo mucho más de lo necesario: lo que si estamos hablando de un millón de elementos?
    • Punto justo. He añadido una alternativa con mejor rendimiento. Ahora ir downvote la aceptación de respuesta, lo que la hace mucho más trabajo que tiene que… 😉

  3. 9

    La mejor manera de detectar la posición es por FindIndex
    Esta función sólo está disponible para la Lista de<>

    Ejemplo

    int id = listMyObject.FindIndex(x => x.Id == 15); 

    Si usted tiene enumerador o uso de la matriz de esta manera

    int id = myEnumerator.ToList().FindIndex(x => x.Id == 15); 

    o

       int id = myArray.ToList().FindIndex(x => x.Id == 15); 
  4. 4

    Estoy de acuerdo en que LINQ no es la mejor solución para este problema, pero aquí es otra variación que es O(n). No ordenar y sólo se recorre la lista de una vez.

    var list = new List<int> { 3, 1, 0, 5 };
    int pos = Enumerable.Range(0, list.Count)
        .Aggregate((a, b) => (list[a] < list[b]) ? a : b); //returns 2
  5. 2
    var data = new List<int> { 3, 1, 0, 5 };
    
    var result = Enumerable.Range(0, data.Count).OrderBy(n => data[n]).First();
  6. 0
    List<int> data = new List<int>();
    data.AddRange(new[] { 3, 1, 0, 5 });
    Console.WriteLine(data.IndexOf(data.Min()));
  7. 0
    int min = 0;
    bool minIsSet = false;
    
    var result = ints
      .Select( (x, i) => new {x, i}
      .OrderBy(z => z.x)
      .Select(z => 
      {
        if (!minIsSet)
        {
          min = z.x;
          minIsSet = true;
        }
        return z;
      }
      .TakeWhile(z => z.x == min)
      .Select(z => z.i);
  8. 0

    No necesariamente recomendar esta CPS-código de estilo, pero funciona y es O(n), a diferencia de las soluciones que se utiliza OrderBy:

    var minIndex = list.Aggregate(
        new { i = 0, mini = -1, minv = int.MaxValue },
        (min, x) => (min.minv > x)
            ? new { i = min.i + 1, mini = min.i, minv = x }
            : new { i = min.i + 1, mini = min.mini, minv = min.minv })
        .mini;

    Cambio > a >= si desea que el último mínimo duplicar, no de la primera.

    Uso .minv para obtener el valor mínimo o ninguno de los dos para obtener una 2-tupla con el índice y el valor mínimo.

    No puedo esperar para .NET para obtener las tuplas en la versión 4.0.

  9. -1
    List<int>.Enumerator e = l.GetEnumerator();
    int p = 0, min = int.MaxValue, pos = -1;
    while (e.MoveNext())
    {
        if (e.Current < min)
        {
            min = e.Current;
            pos = p;
        }
        ++p;
    }
    • Esta respuesta era humorístico creo 🙂

Dejar respuesta

Please enter your comment!
Please enter your name here