0

So this is my code right now, and I need help so it won't makes duplicates. I need this for school so if you could explain a little bit too it would be helpful. Btw don't care about the comments it's on Swedish

        int temp;

        int[] myArray = new int[20]; // Array med 20 tal
        Random random = new Random(); // Skapar metoden "Random"
        for (int i = 0; i < myArray.Length; i++) // Forloop med 20 positioner
        {

            myArray[i] = random.Next(1, 100); // Ger random värden till dessa 20 positionerna
            for (int j = 0; j < myArray.Length; j++)
            {
                if (myArray[i] > myArray[j]) // Array [i] större än Array [j]
                {
                    //temp = myArray[j];
                    //myArray[j] = myArray[i];  
                    //myArray[i] = temp;

                }
            }
            Console.Write(myArray[i] + " ");
        }
Adam
  • 1
  • 1
  • 4
  • 5
    Use a `HashSet` instead of an array of `int` and then do `hashSet.ToArray()` – dcg Mar 17 '17 at 12:32
  • Beat me to it dcg :) Yes HashSet is your best bet if you don't care about the order of the elements – Daniel Wardin Mar 17 '17 at 12:33
  • 1
    If it's a school task it's most likely not enough to just use `HashSet` but to show the logic behind it. – Lloyd Mar 17 '17 at 12:34
  • 1
    Why do you need Random if your array has as size of 20, your random number range is [1;21] and you don't want any duplicates? It looks more like you need to shuffle a sequence of elements 1 to 20. [C# Shuffle](http://stackoverflow.com/questions/273313/randomize-a-listt) – smkanadl Mar 17 '17 at 12:34
  • you should move the inner loop out, first you create array and initialize it from 1 to 20. then start to shuffle it. similar to sort algorithm but this time with condition that is randomly true or false. although there are better shuffle algorithms like fisher yates shuffle algorithm https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle – M.kazem Akhgary Mar 17 '17 at 12:35
  • 1
    Looks like you want the numbers 1-20 in random order. So another way would be to fill the array sequentially and then shuffle it. For example with `array = array.OrderBy(x => random.Next()).ToArray();` – Corak Mar 17 '17 at 12:35
  • Your code creates array of 20 elements with unique value in each element that too between 1 and 20. And then sorts the array. You dont need to use random for this. You can simply assign `myArray [i] = i+1;`. That will give sorted array containing unique value in each element. – Chetan Mar 17 '17 at 12:39
  • Because it's for school. Have you any reglementations? Should you use some special technics? Have you already worked with do while loops or LINQ? – Mighty Badaboom Mar 17 '17 at 12:40
  • I added another part to my answer. Please take a look. – Stefan Steinegger Mar 20 '17 at 07:42

3 Answers3

3

you can try linq to .Distinct() and to convert it to array use .ToArray()

var s = { 5, 7, 7, 4, 3};
var q = s.Distinct().ToArray();
NinjaDeveloper
  • 1,620
  • 3
  • 19
  • 51
1

Since the array has exatly the size of the random value range (which is 20), you will get every number exactly once. It's easiest to create every number once using Enumerable.Range and only change the order in which they appear.

Changing the order can be done by OrderBy(), while random is used here.

This is all based on IEnumerable<T>. So it needs to be put into an array, which is simply done by calling ToArray().

public int[] RandomlyOrderedValues()
{
  Random random = new Random();
  return Enumerable.Range(1, 20).OrderBy(x => random.Next()).ToArray();
}

I'm not your teacher but hope you still play around by yourself, read the docs and finally express it in your own words.


Changed question, now the random range is larger than the array size.

It's always best to work with IEnumerable<T>, there you get the most powerful tools.

// let's create inifite number of random values:
// note that the Random instance needs to be created only once,
// so it's put into a field.

private Random random = new Random();

public IEnumerable<int> InfiniteRandomValues()
{
  while (true)
  {
    yield return random.Next(1, 100);
  }
}

public int[] GetUniqueRandomValues(int numberOfValues)
{
  return InfiniteRandomValues()
    // only uninque values
    .Distinct()
    // generate the requested number of distinct values
    .Take(numberOfValues)
    // put it into an array.
    .ToArray();
} 

How does it work? When you create random values, you don't know how many it will be, because you cannot know how many duplicates it will create. A generator for an infinite number of values has certainly enough values. Think of it as a factory. Only when the IEnumerable is iterated, the values are created.

This is called "deferred execution". Only when you iterate the IEnumerable, the values are requested by the source.

Distinct works like this. It returns only as many distinct values as are requested by its caller.

Which is Take. This one reduces the number of items that are taken, but still doesn't iterate itselves.

ToArray finally iterates its source and pulls as many values as there are. Read it backwards now: It takes all values from Take, which returns 20. Itselves it takes 20 values from Distinct, which iterates its source until it got 20 distinct values. Distinct takes its values from the InifiteRandomNumbers factory and can take as many as it needs.

When you finally understand how these things work, you can use it quite intuitively.


Another, more classic implemenation

private int[] GetRandomValues()
{
  Random random = new Random();

  int[] values = new int[20];

  for(int i = 0; i < 20; i++)
  {
    // create random values until you found a distinct oune.
    int nextValue;
    do
    {
      nextValue = random.Next(1, 100);
    } while (ContainsValue(values, i, nextValue))

    values[i] = nextValue;
  } 
  return values;
}

// When adding the values to a List instead of an array, it would be
// much easier, but need copying the vlaues to the array at the end.
// When using the array directly, you have to know which values you
// already generated, because it's initialized with zero.
// This method checks wether the value is in the array within
// the items until endIndex.
private bool ContainsValue(int[] values, int endIndex, int valueToFind)
{
  // simple linq way:
  // return values.Take(endIndex).Contains(valueToFind);

  // classic way:
  for(int i = 0; i < endIndex; i++)
  {
    if (values[i] = valueToFind) return true;
  }
  return false;
}
Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193
1

At it's simplest, it looks like you probably want to

private static Random rng = new Random(); //class level definition

var myArray = Enumerable.Range(1, 20).OrderBy(X => rng.Next()).ToArray();

Alternatively, if this is for school and you need to justify your code... fill an array with the numbers 1 to 20, then use a Fisher-Yates shuffle to randomise the order of the array.

See: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

Community
  • 1
  • 1
spender
  • 117,338
  • 33
  • 229
  • 351