2012-05-06 2 views
1

J'ai un ensemble de chaînes uniques, et je souhaite les montrer avec une couleur. Les cordes se répètent chaque fois ici et là donc j'ai besoin de la couleur pour être cohérente, pas aléatoire. Une approche serait de randomiser la couleur et l'enregistrer dans Dictionary ou quelque chose comme ça afin que je puisse utiliser la même couleur à nouveau.Comment créer un System.Drawing.Color arbitraire sur une chaîne?

Une autre approche serait de trouver un algorithme/logique simple qui transforme en quelque sorte une chaîne en System.Drawing.Color. Cependant, je voudrais le garder à un ensemble de couleurs prédéfinies, de sorte que je ne finis pas avec des couleurs pas si bonnes. Appelons cela List<Color> allowedColors.

J'ai essayé Convert.ToByte() et j'ai pensé que j'utiliserais l'octet pour les composants R, G et B de Color, mais cela n'a pas fonctionné parce que la conversion ne fonctionne pas de cette façon. Une chaîne est juste une simple chaîne String foo = "bar";. La relation entre la couleur et la chaîne n'a pas d'importance tant qu'elle est cohérente, c'est-à-dire que chaque fois que le programme est exécuté, il doit être égal à la même couleur et les couleurs doivent généralement être différentes pour chaque chaîne. couleurs car il y a plus de chaînes que de couleurs et ce n'est pas un mapping one-to-one).

Ces chaînes proviennent d'une source que je ne contrôle pas. Ils sont uniques, mais varient. Chaque fois que le programme est démarré et si la même chaîne apparaît, elle doit être de la même couleur. Donc, je pense que je suis à la recherche d'une sorte de transformation de chaîne à octet qui, lorsqu'elle chevauche la plage d'octets, finit par être mappée sur RGB et envoyée à Color.FromArgb().

+0

Quel type de cordes? –

+0

Pourriez-vous au moins donner un exemple du type de chaîne dont vous parlez? Quelle est la relation attendue entre la chaîne et la couleur résultante? –

+0

La classe StringConverter fait du bon travail en gérant différents formats de chaînes et en reconnaissant les couleurs nommées. Ne le rends pas trop arbitraire. –

Répondre

1

Je pense que le plus simple L'approche est simplement d'attribuer à chaque chaîne la couleur disponible suivante dans votre liste AvailableColors et de sauvegarder ce mappage, la première fois que vous le faites, dans un dictionnaire. Cela peut être enregistré sur disque à l'aide de la sérialisation et réutilisé dans les exécutions ultérieures. Voici quelques (mise à jour) exemple de code:

public Color[] AvailableColors = new Color[] { Colors.Red, Colors.Blue, Colors.Green};   
private int _nextColorIndex = 0; 
public Dictionary<string,Color> ColorMappings = new Dictionary<string,Color>(); 
public Color GetNextColor() 
{ 
    Color nextColor = AvailableColors[_nextColorIndex]; 
    _nextColorIndex++; 
    if (_nextColorIndex == AvailableColors.Length) 
     _nextColorIndex = 0; // Restart colors and reuse. 
    return nextColor; 
} 

public void AssignColor (string myString) 
{ 
    ColorMappings.Add(myString, GetNextColor()); 
} 

Vous devez utiliser une gestion appropriée lorsque vous exécutez des chaînes, bien sûr, et peut-être des verrous de concurrence autour GetNextColor si vous le faites multithread, mais il est un début.

+0

Idée intéressante. Vous pouvez implémenter 'AvailableColors' en tant que file d'attente et une méthode' GetNextColor' qui renvoie l'élément suivant dans la file d'attente, puis l'ajoute à la fin de la file d'attente. –

+0

Je pense que vous pouvez également utiliser l'opérateur mod, AvailablrColors [_nextColorIndex% AvailableColors.Length] et continuer à incrémenter l'index pour toujours. –

+0

Jim: c'est une solution plus élégante, mais plus complexe - apportant des classes newfangled et autres joyeusetés. :) Aaron: Oui, ça marcherait bien. Eh bien, pour les 2 147 483 647 premières chaînes, de toute façon. :) –

1

Si vous avez un ensemble de chaînes uniques connues et un ensemble de couleurs prédéfinies, il suffit d'utiliser un dictionnaire:

Dictionary<string, Color> StringColors = new Dictionary<string, Color>() 
{ 
    {"string1", Colors.Red}, 
    {"string2", Colors.Green}, 
    {"string3", Colors.Blue}, 
}; 

Et il est aussi simple que:

string theString = "string2"; 
var MyColor = StringColors[theString]; 
+0

Je suppose que c'est logique, même si j'ai besoin de l'adapter un peu car les chaînes qui sont uniques ne sont toujours pas "codées" mais proviennent d'une source. – Tower

1

Vous pouvez faire une liste des couleurs à l'aide de la méthode FramArgb:

var allowedColors = new List<Color>(); 
allowedColors.Add(Color.FromArgb(255, 0, 0)); 

Vous pouvez gérer un mappage de chaînes aux couleurs avec un dictionnaire:

var colorMap = new Dictionary<string, Color>(); 
colorMap.Add("red", Color.FromArgb(255, 0, 0)); 

Dans de nombreux cas, cela être considéré comme une solution sur-ingénierie, mais en tout cas c'est un exemple d'encapsulation en C#:

class AppString 
{ 
    private string text; 
    private Color color; 

    public AppString(string text, Color color) 
    { 
    this.text = text; 
    if(allowedColors.Contains(color)) 
    { 
     this.color = color; 
    } 
    else 
    { 
     throw new Exception("invalid color"); 
    } 
    } 

    // This lets you use an AppString most places where you used a regular string. 
    public static implicit operator string(AppString appString) 
    { 
     return appString.text; 
    } 

    // This lets you use an AppString most places where you used a Color. 
    public static implicit operator Color(AppString appString) 
    { 
     return appString.color; 
    } 

    // OR if you don't prefer overloading the implicit cast, a standard pattern 
    // is to use a Value property. 
    public string Value { get { return this.text; } } 
    public Color Color { get { return this.color; } } 
} 
Questions connexes