2017-06-07 2 views
1

bekommen Wenn auf diese Weise ich Zufallswert aus gegebenem Bereich erhalten kann:Wie Zufallswert aus bestimmten Bereichen des Wörterbuchinhhalt

int r = ran.Next(1, 4); 
string v; 
if (dict.TryGetValue(r, out v)) 
{ 
    ///... 
} 

, wie man richtig Zufallswert von <int, string> Wörterbuchinhhalt von bestimmtem Bereich bekommen, nur zum Beispiel von 4 bis 6 und 1 und 2 und vermeiden sucht 3:

Dictionary<int, string> dict = new Dictionary<int, string>() 
{ 
    { 1, "word1" }, 
    { 2, "word2" }, 
    { 3, "word3" }, 
    { 4, "word4" }, 
    { 5, "word5" }, 
    { 6, "word6" } 
}; 
+1

Wie garantieren Sie, dass alle Werte im Bereich existieren in das 'Dictionary' und wenn du kannst, warum nicht einfach ein' array'/'List' verwenden, um es anstelle eines' Dictionary' zu speichern – Vikhram

+0

@ Vikhram Hallo, garantiert, weil es keine aktualisierte Liste ist. und, ja mit List oder Array ist es einfach und nützlich, aber ich wundere mich über Wörterbuch , wenn es möglich ist –

Antwort

-1

Hier ist eine Lösung, die eine Erweiterung Methode:

public static class RandomExtensions 
{ 
    public static int NextWithinRange(this Random random, params Range[] ranges) 
    { 
     if (ranges.Length > 0) 
     { 
      Range range = ranges[random.Next(0, ranges.Length)]; 
      return random.Next(range.MinValue, range.MaxValue + 1); 
     } 

     return random.Next(); 
    } 

    public class Range 
    { 
     public int MinValue { get; set; } 
     public int MaxValue { get; set; } 

     public Range(int minValue, int maxValue) 
     { 
      MinValue = minValue; 
      MaxValue = maxValue; 
     } 
    } 
} 

Verbrauch:

int r = ran.NextWithinRange(new Range(1, 2), new Range(4, 6)); 
string v; 
if (dict.TryGetValue(r, out v)) 
{ 
    ///... 
} 

Hier ist eine Lösung mithilfe von LINQ: für den Hinweis auf das Potenzial ArgumentOutOfRange Ausnahme in meinem ersten Beitrag dank @ Kyle:

var rand = new Random(); 

// create a new dictionary, filtering out any unwanted keys within range(s) 
Dictionary<int, string> filteredDict = 
    dict.Where(pair => (pair.Key >= 1 && pair.Key <= 2) 
        || (pair.Key >= 4 && pair.Key <= 6)) 
     .ToDictionary(pair => pair.Key, pair => pair.Value); 

// get a random entry from the filtered dictionary 
KeyValuePair<int, string> entry = filteredDict.ElementAt(rand.Next(0, filteredDict.Count)); 

// get random entry's value 
string value = entry.Value; 

EDIT.

+0

Dies kann fehlschlagen, wenn das Wörterbuch die ausgeschlossenen Schlüssel enthält, da die ausgewählte Zufallszahl größer als die Anzahl der verbleibenden sein kann Schlüssel-Wert-Paare. Dies bewirkt, dass 'ElementAt' eine 'ArgumentOutOfRange'-Ausnahme auslöst. – Kyle

+0

Aktualisierter Beitrag, danke @Kyle! –

0

HashSet erstellen mit ausgeschlossenen Werte dann

HashSet<int> excludedValues = .... 
List<int> values = dict.Where(x=> excludedValues.Contains(x.Key) == false).Select(x=>x.Key).ToList(); 

int index = rand.Next(1, values.Count); 
string value = dict[index]; 

diese Weise können Sie auf ohne Wert beschränkt werden 3. Sie können alles in dieser Sammlung setzen. Wenn Ihre Sammlungen groß sind, sollten Sie Hashset verwenden, das viel schneller ist als List.

0

Im Allgemeinen gibt es ein paar Funktionen, die in LINQ nämlich IEnumerable.Skip und IEnumerable.Take

Diese Funktionen verwendet werden können, ein Stück von jedem IEnumerable zu bekommen. Denken Sie daran, dass Dictionary<TKey, TValue> auch ein IEnumerable<KeyValuePair<TKey, TValue>>

So ist ein zufälliges Element zwischen dem 4. und 10. Element zugreifen.

var rand = new Random(); 
dict.Skip(3).Take(6 /* 10 - 4 */).ElementAt(rand.Next(6 /* 10 - 4 */) 

Denken Sie daran, dass die Sequenz nicht unbedingt durch den Schlüssel oder in irgendeiner vorhersehbaren Weise sortiert oder sequenziert wird. Sie müssen möglicherweise OrderBy verwenden, um das Wörterbuch in der von Ihnen gewählten Reihenfolge zu durchlaufen.

Wenn Sie tun möchten, greifen Sie auf diese Dinge viele Male zwischen dem Wörterbuch immer aktualisiert, dann einfach dict.Keys.OrderBy().ToList() und dann diese List Zugriff auf die gleichen Skip().Take().ElementAt() oder direkt mit dem Index Manipulationen verwendet. Dies wird wieder Aufzählen der gleiche Wörterbuch mehrmals

vermeiden
0

Sie alle Werte sammeln können, die ergriffen werden können, und dann zufällig einen von ihnen wählen:

private static Random s_Random = new Random(); 

    ... 

    var values = dict 
     .Where(pair => pair.Key >= 4 && pair.Key <= 6 || // conditions on key 
        pair.Key >= 1 && pair.Key <= 2) 
     .ToArray(); 

    var result = values[s_Random.Next(values.Length)]; 
0

Mit dieser Lösung Sie einen zufälligen Wert bekommen kann innerhalb angegebene Bereiche, ohne das Wörterbuch zuerst durchlaufen zu müssen.

void Main() 
{ 
    Dictionary<int, string> dict = new Dictionary<int, string>() 
    { 
     { 1, "word1" }, 
     { 2, "word2" }, 
     { 3, "word3" }, 
     { 4, "word4" }, 
     { 5, "word5" }, 
     { 6, "word6" } 
    }; 
    var randomizer = new Random(); 
    GetRandomValue(dict, randomizer, new Range(4, 6), new Range(1,2)).Dump(); 
} 

public TValue GetRandomValue<TValue>(IDictionary<int, TValue> dic, Random randomizer, params Range[] ranges) 
{ 
    var range = ranges[randomizer.Next(0, ranges.Length)]; 
    var key = randomizer.Next(range.From, range.To + 1); 
    return dic[key]; 
} 

public class Range 
{ 
    public Range(int @from, int to) 
    { 
     From = @from; 
     To = to; 
    } 
    public int From {get;set;} 
    public int To {get;set;} 
} 
0

Je nachdem, was genau benötigt wird, könnte der einfachste Weg, die möglichen Zahlen angeben:

int[] a { 1, 2, 4, 5, 6 }; 

int r = a[ran.Next(a.Length)]; 

oder

int r = ran.Next(1, 6); 

if (r == 3) r = 6; 
Verwandte Themen