简体   繁体   English

有清单 <KeyValuePair<int, int> &gt;,使4个值中的1个等于1

[英]With List<KeyValuePair<int, int>>, to make 1 in 4 of the values equal 1

I have a List< KeyValuePair < int,int >>. 我有一个List <KeyValuePair <int,int >>。 (I chose this over a dictionary since multiple keys will be the same (though consecutive keys won't be the same); and because I want to output them in the order input). (我在字典中选择了它,因为多个键将是相同的(尽管连续的键将不相同);并且因为我想按顺序输入来输出它们)。

All the keys are equal to a randNum between 1-5 (inclusive). 所有密钥都等于1-5(含)之间的randNum。 (The keys don't really matter in relation to my problem). (与我的问题无关,键并不重要)。

All the values are the default, 0. 所有值均为默认值0。

I want to change 1 in 4 of the values to equal 1 (the others still equal 0). 我想将4个值中的1个更改为等于1(其他值仍等于0)。 The position of the value=1 in each range of 4 is randomly chosen. 值= 1的位置在4的每个范围内随机选择。

An example output of what I want, printing the KVPs in the list: 我想要的示例输出,在列表中打印KVP:

[5,0]
[3,1]
[2,0]
[5,0]
[1,0]
[4,0]
[2,0]
[3,1]
[1,0]
[5,0]
[4,1]
[2,0]

So, in groups of 4, the values would be: 0100 | 因此,以4为一组,值将是:0100 | 0001 | 0001 | 0010. 0010。

Here's what I've tried to do so far: (the sequence is already set up with all the keys) 到目前为止,这是我尝试做的事情:(已经使用所有键设置了序列)

List<KeyValuePair<int,int>> sequence = new List<KeyValuePair<int,int>>();

// Populate keys in sequence with random numbers 1-5
// ...

public static void SetSequenceValues()
{
    Random randNum = new Random();
    bool allValuesSet = false;

    // count is the max (non-inclusive) in each range of 4
    // i.e. first loop is 1-4
    // then count += 4
    // second loop is 5-8, etc.
    int count = 5;

    while (allValuesSet == false)
    {
        int randPos = randNum.Next(count - 4, count);

        // If changing the first key in the range,
        // the desired key index = count-4
        if (randPos == count - 4)
        {
            var oldKVP = sequence[count - 4];
            sequence[count - 4] = new KeyValuePair<int, int>(oldKVP.Key, 1);
        }
        else if (randPos == count -3)
        {
            var oldKVP = sequence[count - 3];
            sequence[count -3] = new KeyValuePair<int, int>(oldKVP.Key, 1);
        }
        else if (randPos == count - 2)
        {
            var oldKVP = sequence[count - 2];
            sequence[count - 2] = new KeyValuePair<int, int>(oldKVP.Key, 1);
        }
        else if (randPos == count - 1)
        {
            var oldKVP = sequence[count - 1];
            sequence[count - 1] = new KeyValuePair<int, int>(oldKVP.Key, 1);
        }

        // Increase count by 4, so on the next loop, e.g. the range looked at will be 4-8 (not including 8, i.e. 4-7)
        count += 4;

        if (count >= sequence.Count)
            allValuesSet = true;
    }
}

Currently, the output is kind of close-ish, but, occasionally there'll be a couple of 1s in each group. 当前,输出有点接近,但有时每组会有几个1。 Also, I think it may be using groups of 5 rather than 4? 另外,我认为可能使用的是5个而不是4个的组? Though that doesn't seem to entirely be it either. 尽管那也不完全是。

As far as what's broken with the code you posted I think you have an off by 1 issue somewhere. 至于您发布的代码有什么问题,我认为您在某处遇到了1分问题。 It looks like you index into the array starting at [1] when the first key should be [0]. 当第一个键应为[0]时,您似乎从[1]开始索引到数组中。 Try setting count to 4 initially instead of 5. 最初尝试将计数设置为4,而不是5。

...
int count = 4;

while (allValuesSet == false)
{
...

I would recommend trying to use loops and variables in place of hard coded if conditions. 我建议尝试使用循环和变量来代替硬编码的条件。 You have the right idea but you don't need to check the value of the index, you can just use it in place. 您有正确的想法,但无需检查索引的值,只需就地使用它即可。 So you can collapse the following to make it a lot more readable. 因此,您可以折叠以下内容以使其更具可读性。 You could replace all of 您可以替换所有

    // If changing the first key in the range,
    // the desired key index = count-4
    if (randPos == count - 4)
    {
        var oldKVP = sequence[count - 4];
        sequence[count - 4] = new KeyValuePair<int, int>(oldKVP.Key, 1);
    }
    else if (randPos == count -3)
    {
        var oldKVP = sequence[count - 3];
        sequence[count -3] = new KeyValuePair<int, int>(oldKVP.Key, 1);
    }
    else if (randPos == count - 2)
    {
        var oldKVP = sequence[count - 2];
        sequence[count - 2] = new KeyValuePair<int, int>(oldKVP.Key, 1);
    }
    else if (randPos == count - 1)
    {
        var oldKVP = sequence[count - 1];
        sequence[count - 1] = new KeyValuePair<int, int>(oldKVP.Key, 1);
    }

With

var oldKVP = sequence[randPos];
sequence[randPos] = new KeyValuePair<int, int>(oldKVP.Key, 1);

To do what you want to do in a more generalized fashion I would do as below 为了以更通用的方式完成您想做的事情,我将按照以下步骤进行操作

using System;
using System.Collections.Generic;

namespace KvpSequence
{
    class Program
    {
        const int numberOfSequences = 4; // each sequence is a set of 4 ints between 1 and 5
        static void Main(string[] args)
        {
            List<KeyValuePair<int, int>> sequence = new List<KeyValuePair<int, int>>(numberOfSequences * 4);
            Random rand = new Random();

            for (int i = 0; i < numberOfSequences; ++i) {
                var indexToSet = rand.Next(0, 4);
                for (int j = 0; j < 4; ++j)
                    sequence.Add(new KeyValuePair<int, int>(rand.Next(1, 6), j == indexToSet ? 1 : 0));
            }

            foreach (var kvp in sequence)
                Console.WriteLine(kvp);
        }
    }
}

This would be much easier if you used a Dictionary<int, List<int>> . 如果使用Dictionary<int, List<int>>这会容易得多。 You can just loop through each key and assign a random entry in the collection to 1: 您可以循环浏览每个键,然后将集合中的随机条目分配给1:

var data = new Dictionary<int, List<int>>();
data.Add(1, new List<int> { 0, 0, 0, 0, 0 });
// continue filling the dictionary...

var random = new Random();
foreach (var entry in data)
{
    entry.Value[random.Next(0, entry.Value.Count - 1)] = 1;
}

// print the results

foreach (var entry in data)
{
    Console.WriteLine("{0} => {1}", entry.Key, entry.Value.Join(", "));
}

If I understand your intent correctly, here is what you might do 如果我正确理解您的意图,那么您可能会这样做

public class BucketsWithRandomValues
{
    private Random random = new Random();

    public void FillWithValuesInEachBucket(IList<KeyValuePair<int, int>> list, int bucketSize = 4, int valueToPut = 1)
    {
        if (list == null) throw new ArgumentNullException(nameof(list));

        int i = 0;
        while (i + bucketSize <= list.Count)
        {
            var index = random.Next(i, i + bucketSize); // exclusive upper bound
            list[index] = new KeyValuePair<int, int>(list[index].Key, valueToPut);
            i += bucketSize;
        }
    }
}

I would also suggest using a ValueTuple instead of KeyValuePair since you don't really have the Key-Value semantics because of possible duplicate keys. 我还建议您使用ValueTuple而不是KeyValuePair,因为由于可能存在重复的键,您实际上并没有键值语义。 When people see KeyValuePair they immediately think Dictionary, not List. 当人们看到KeyValuePair时,他们会立即想到Dictionary,而不是List。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM