Shuffle string array without duplicates

2019-08-01 09:40发布

I am using the Knuth-Fisher-Yates algorithm to display a shuffled array of string items on a windows form. I do not get any duplicates, which is what I was trying to achieve, however, it only spits out 12 of the 13 elements of the array. How can I get it to display all 13 elements of the array? Here is my code:

private void FormBlue1_Load(object sender, EventArgs e)
{
// set the forms borderstyle
this.FormBorderStyle = FormBorderStyle.Fixed3D;

// create array of stationOneParts to display on form
string[] stationOneParts = new string[13];
stationOneParts[0] = "20-packing";
stationOneParts[1] = "5269-stempad";
stationOneParts[2] = "5112-freeze plug";
stationOneParts[3] = "2644-o'ring";
stationOneParts[4] = "5347-stem";
stationOneParts[5] = "4350-top packing";
stationOneParts[6] = "5084-3n1 body";
stationOneParts[7] = "4472-packing washer";
stationOneParts[8] = "3744-vr valve o'ring";
stationOneParts[9] = "2061-packing spring";
stationOneParts[10] = "2037-packing nut";
stationOneParts[11] = "2015-latch ring";
stationOneParts[12] = "stem assembly";

Random parts = new Random();

// loop through stationOneParts using a Swap method to shuffle
labelBlueOne.Text = "\n";
for (int i = stationOneParts.Length - 1; i > 0; i--)
{
int j = parts.Next(i + 1);
Swap(ref stationOneParts[i], ref stationOneParts[j]);

// display in a random order
labelBlueOne.Text += stationOneParts[i] + "\n";
}
}

private void Swap(ref string firstElement, ref string secondElement)
{
string temp = firstElement;
firstElement = secondElement;
secondElement = temp;
}

标签: c# .net-4.0
5条回答
萌系小妹纸
2楼-- · 2019-08-01 09:54

Simpliest approach :

        Random rnd = new Random();
        var stationOneParts = new List<string>{
        "20-packing",
        "5269-stempad",
        "5112-freeze plug",
        "2644-o'ring",
        "5347-stem",
        "4350-top packing",
        "5084-3n1 body",
        "4472-packing washer",
        "3744-vr valve o'ring",
        "2061-packing spring",
        "2037-packing nut",
        "2015-latch ring",
        "stem assembly"}.OrderBy(s => rnd.Next());

        labelBlueOne.Text = string.Join(Environment.NewLine, stationOneParts);
查看更多
Juvenile、少年°
3楼-- · 2019-08-01 09:56

Change your loop condition to i >= 0.

查看更多
甜甜的少女心
4楼-- · 2019-08-01 10:02

You don't access the first element. for (int i = stationOneParts.Length - 1; i >= 0; i--).

查看更多
Viruses.
5楼-- · 2019-08-01 10:04

Since you mention C# 4.0, why not write is C#-ish?

using System.Linq;

// ...

    var stationOneParts = new [] { "20-packing",
        "5269-stempad",
        "5112-freeze plug",
        "2644-o'ring",
        "5347-stem",
        "4350-top packing",
        "5084-3n1 body",
        "4472-packing washer",
        "3744-vr valve o'ring",
        "2061-packing spring",
        "2037-packing nut",
        "2015-latch ring",
        "stem assembly" };

    Random rand = new Random();
    stationOneParts = stationOneParts
        .Distinct() // see subject: '... without duplicates'
        .Select(i => new { i, key=rand.Next() })
        .OrderBy(p => p.key)
        .Select(p => p.i)
        .ToArray();
查看更多
何必那么认真
6楼-- · 2019-08-01 10:12

As you are showing the texts using the loop that swaps the items, you will not show the last item, because it's never swapped by itself.

Just show the last item after the loop:

labelBlueOne.Text += stationOneParts[0] + "\n";

Alternatively, you can display all the items outside the loop that shuffles them:

for (int i = stationOneParts.Length - 1; i > 0; i--) {
  Swap(ref stationOneParts[i], ref stationOneParts[parts.Next(i + 1)]);
}
labelBlueOne.Text = "\n" + String.Join("\n", stationOneParts);
查看更多
登录 后发表回答