2011-09-21 24 views
6

quiero para almacenar datos tales comoqué colección de C# usar en lugar de List <KeyValuePair <string, double >>?

{ 
{"apple",15 } 
{"pear",12.5 } 
{"", 10  } 
{"", 0.45  } 
} 

se trazan los datos en un gráfico de barras (cadena será la leyenda y el doble será el valor) orden de inserción es importante. Perfs no importan. Las cadenas podrían estar duplicadas o vacías. (también se pueden duplicar los valores)

Necesito obtener valores mínimos y máximos (si es posible si es posible) para establecer la escala.

utilizo

List<KeyValuePair<string, double>> data = new List<KeyValuePair<string, double>>(); 
data.Add(new KeyValuePair<string,double>("",i)); 

bastante aburrido e ilegible. ¿Hay una manera más limpia de hacerlo?

StringDoubleCollection data = new StringDoubleCollection(); 
data.add("apple",15); 
data.add("",10); 

double max = data.values.Max(); 
double min = data.values.Min(); 

si no la forma de obtener el valor máximo de List<KeyValuePair<string, double>> sin demasiados problemas

NameValueCollection se ve bien, pero es un <string,string> necesito un <string,double>

gracias

+0

stackoverflow mató mi publicación al no escapar de algunos '<'. Así que mi último comentario fue cómo obtener el valor máximo de List > y NameValueCollection es bueno, pero es un Necesito un frenchone

+0

corregí el formato por usted. – Ray

+0

Lo que quiere es básicamente un diccionario que permite duplicar claves. De acuerdo con esta pregunta: http://stackoverflow.com/questions/146204/duplicate-keys-in-net-dictionaries no hay nada en el Framework que lo soporte. Probablemente necesites crear tu propia versión genérica de NameValueCollection. –

Respuesta

1

Para determinar qué estructura de datos realmente quiere, veamos sus patrones de uso.

  • Insertar orden importa.
  • No accede a sus elementos por clave.
  • Desea mín. Y máx.

Un montón ofrece mín. o máximo, pero no conserva el orden. Un diccionario basado en hash tampoco conserva el orden. Una lista es realmente una buena opción para su estructura de datos. Está disponible y ofrece un excelente soporte.

Puede embellecer su código definiendo clases tanto para la estructura de datos como para los datos de su barra. Y puede agregar funcionalidad min/max a la colección. Nota: No utilicé las funciones Linq Min/Max, porque devuelven el valor mínimo, no el elemento mínimo.

public class BarGraphData { 
    public string Legend { get; set; } 
    public double Value { get; set; } 
} 

public class BarGraphDataCollection : List<BarGraphData> { 
    // add necessary constructors, if any 

    public BarGraphData Min() { 
     BarGraphData min = null; 
     // finds the minmum item 
     // prefers the item with the lowest index 
     foreach (BarGraphData item in this) { 
      if (min == null) 
       min = item; 
      else if (item.Value < min.Value) 
       min = item; 
     } 
     if (min == null) 
      throw new InvalidOperationException("The list is empty."); 
     return min; 
    } 

    public BarGraphData Max() { 
     // similar implementation as Min 
    } 
} 
1

Ha estudiado LookUp?

El único problema es que es inmutable, por lo que debe ser capaz de crear su colección de una sola vez.

Como señala Anthony Pegram, es un poco de dolor crear una. Depende de dónde provienen sus datos. Eche un vistazo al método ToLookup.

+1

El problema con esto es que no es directamente instanciable. Empiezas de otra manera y luego puedes proyectar esto. Primero necesitaría una estructura intermediaria. –

+0

Sí, eso es cierto. Pero aún podría ser posible dependiendo de dónde provengan sus datos (no se proporcionó información). Vale la pena saberlo en cualquier caso. – Ray

5

Se puede crear una clase como la siguiente:

class X 
{ 
    public string Name { get; set; } 
    public double Value { get; set; } 

    // name is an optional parameter (this means it can be used only in C# 4) 
    public X(double value, string name = "") 
    { 
     this.Name = name; 
     this.Value = value; 
    } 

    // whatever 
} 

Y a continuación, obtener los valores máximos y mínimos utilizando LINQ con un selector:

var data = new List<X>(); 
data.Add(new X(35.0, "Apple")) 
data.Add(new X(50.0)); 

double max = data.Max(a => a.Value); 
double min = data.Min(a => a.Value); 

EDIT: si el código anterior todavía parece ilegible para usted, intente mejorarlo utilizando un operador para los casos en los que desea tener solo el valor.

// Inside X class... 
public static implicit operator X(double d) 
{ 
    return new X(d); 
} 

// Somewhere else... 
data.Add(50.0); 
+0

Y "Insertar pedido es importante." ... –

+0

Lo siento, salté la parte * duplicados * al leer. Editado de todos modos :) –

+0

Sería una buena idea eliminar el bit del diccionario en lugar de dejar que su edición lo explique. Una clase de encapsulamiento es una sugerencia valiosa, por lo que he votado la respuesta. –

1

Si vale la pena para su uso (es decir, que está utilizando colecciones difíciles de List<KeyValuePair<string, double>> todas partes, que sólo podría valer la pena para implementar StringDoubleCollection. No sería tan difícil para envolver la colección subyacente con el más amigable sintaxis que se ha descrito en el ejemplo.

Y, como otros comentarios/respuestas están sugiriendo, no parece que el marco para proporcionar una solución más simple que coincide con todas sus necesidades ...

en cuanto a " valor máximo ", supongo que te refieres al par clave-valor con el mayor valor.Se puede recuperar de este modo:

var max = list.Select(kvp => kvp.Value).Max(); 
0

Sólo definir su propio modelo de clase para mantener los datos en lugar de depender de un KeyValuePair y todo se vuelve más limpio:

using System; 
using System.Collections.Generic; 

public class Fruit 
{ 
    public string Name {get; set;} 
    public double Price {get; set;} 
} 

public class Program 
{ 
    public static void Main() 
    { 
     List<Fruit> _myFruit = new List<Fruit>(); 

     _myFruit.Add(new Fruit{Name="apple", Price=15 }); 
     _myFruit.Add(new Fruit{Name="pear", Price=12.5 }); 
     _myFruit.Add(new Fruit{Name="", Price=10  }); 
     _myFruit.Add(new Fruit{Name="", Price=0.45  }); 

     // etc... 
    } 
} 
0

¿Qué pasa con la aplicación de la StringDoubleCollection a trabajar como usted quiere ...

public class StringDoubleCollection 
{ 
    private List<KeyValuePair<string, double>> myValues; 
    public List<double> values 
    { 
     get { return myValues.Select(keyValuePair => keyValuePair.Value).ToList(); } 
    } 

    public void add(string key, double value) 
    { 
     myValues.Add(new KeyValuePair<string,double>(key,value)); 
    } 
} 
Cuestiones relacionadas