Set value to a random property from list - c#

Please check the code below. I am trying to set value to a random property of a int list. Problem is that even after i set 5 to a random list this value getting inserted to that property. What am I doing wrong here?
var TransactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
TransactionList.Add(0);
}
var randTransaction = TransactionList.OrderBy(x => Guid.NewGuid()).FirstOrDefault();
//here i am trying to set 5 value to a random TrnasactionList but this not being set
randTransaction = 5;

Try like below. new Random().Next(0, 59); will return value between 0 and 59. Or you can better set it like new Random().Next(0, TransactionList.Count); for it to be dynamic with list.
new Random().Next(minValue, maxValue); The maxValue for the upper-bound in the Next() method is exclusive—the range includes minValue, maxValue-1, and all numbers in between.
var TransactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
TransactionList.Add(0);
}
// var index = new Random().Next(0, 59);
// Below will work for dynamic length of list.
var index = new Random().Next(0, TransactionList.Count);
TransactionList[index] = 5;

If you don't mind the original list getting sorted you could do this:
class Program
{
static void Main(string[] args)
{
var transactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
//I initialized the list with i instead of 0 to better see sorting in place
transactionList.Add(i);
}
transactionList.Sort(new RandomComparer());
//changed it to 99 to spot it more easily
transactionList[0] = 99;
foreach (var i in transactionList)
Console.WriteLine(i);
}
}
public class RandomComparer : IComparer<int>
{
private Random _random = new Random();
public int Compare(int x, int y)
{
return _random.Next(-1, 2);
}
}
See it in action:
https://dotnetfiddle.net/NKuPdx

randTransaction is "int" data type, which is primitive data type.
if you want to set randTransaction that reflect to it's object, just set the object it self

Related

How can I add objects Cbook to my class CBooks without using lists

Cbooks has an atribute "CTeam[] Teams" and it is of fixed size (8). If I want to add objects to it using this in the Main:
CBook A1 = new CBook("Title1", "Author1");
CBook A2 = new CBook("Title1", "Author2");
CBooks ArrayOfBooks = new CBooks(8);
ArrayOfBooks.Add(A1);
ArrayOfBooks.Add(A2);
then position 0 and 1 are ocuppied, and the positions from 2 to 7 are null. What I want to do is, using a variable "int aux=0", count the ocupied positions like this:
for (int k = 0; k < NumberOfTeams; k++)
{
if (Teams[k].Name=="")
Aux += 1;
}
So, Aux in this case would be 2, then I want to do "Teams[Aux] = A" so that A would be in the position 2 and now I should have three objects in my array. But I'm getting "Index out of bound"
Your implementation then should look similar to this:
public class Program
{
public static void Main(string[] args)
{
Element a = new Element("A");
Element b = new Element("B");
MyArray array = new MyArray(8);
array.Add(a);
array.Add(b);
Console.WriteLine(array.Count()); //2 Elements are in the array
}
}
//Sample element class.
public class Element{
public readonly String MyString;
public Element(String myString){
MyString = myString;
}
}
//Sample array class.
public class MyArray{
private readonly Element[] myArray;
private int count; //Use a property here
public MyArray(int size){
//Be careful -> check if size is >= 0.
myArray = new Element[size];
}
public bool Add(Element element){
if(myArray.Length == count) // return false if no more elements fit.
return false;
myArray[count] = element;
count++;
return true;
}
public int Count(){
return count;
}
}
So there is no need for creating an extra count loop. Your "count" variable in "MyArray" class holds always the correct value.
Anyway the implementation or use case of this code is a little bit clunky.
Why are you cant use directly a more safe list or something. That would be a better solution.
What do you need CBooks for? From what I understand, it's just an array of 8 CBook objects so why not use CBook[]?
CBook A1 = new CBook("Title1", "Author1");
CBook A2 = new CBook("Title1", "Author2");
CBooks[] ArrayOfBooks = new CBook[8];
ArrayOfBooks[0] = A1;
ArrayOfBooks[1] = A2;
int aux = 0;
for (int k = 0; k < ArrayOfBooks.Length; k++)
{
//break the loop because we know there are no more books
if (ArrayOfBooks[k] == null)
break;
aux++;
}
The question doesn't cover what the variables NumberOfTeams and Teams are for but could those be added to the implementation of CBook?

Generate 4 differents numbers randomly

I am a novice in Xamarin ,
I want to generate randomly 4 numbers which are in a list and this 4 numbers must be different .
In the example below I have a list of Ids and I am trying to pick 4 id randomly in the list and those 4 Ids must be each differents.
Here is my methode, I cannot see how I can continue and make it simple :
public MyWordsList()
{
InitializeComponent();
Dictionary<int, int> WordId = new Dictionary<int, int>();
int u= 0;
// TestAnswer.IsVisible = false;
foreach (var w in mywords)
{
WordId[u] = w.ID;
u++;
}
Random rnd = new Random();
// this is not ok because I can have the same number
word11.Text = WordsList[rnd.Next(1, 20)];
word12.Text = WordsList[rnd.Next(1, 20)];
word13.Text = WordsList[rnd.Next(1, 20)];
word14.Text = WordsList[rnd.Next(1, 20)];
}
If you have a better solution, I will take.
Thanks
You can write a short generic function which picks X amount of random and unique items from a specified collection and returns them:
private static IEnumerable<T> GetUniqueRandomItems<T>(int count, IList<T> allItems)
{
if (new HashSet<T>(allItems).Count < count)
{
throw new ArgumentException(nameof(allItems));
}
Random random = new Random();
HashSet<T> items = new HashSet<T>();
while (items.Count < count)
{
T value = allItems[random.Next(0, allItems.Count)];
items.Add(value);
}
return items;
}
You can later use it like this:
string[] randomIds = GetUniqueRandomItems(4, WordsList).ToArray();
word11.Text = randomIds[0];
word12.Text = randomIds[1];
word13.Text = randomIds[2];
word14.Text = randomIds[3];
call a method like the following:
private int CreateUniqueRandom(int min, int max, ICollection<int> existingNums)
{
var rnd = new Random();
var newNum = rnd.Next(min, max);
while (existingNums.Contains(newNum))
newNum = rnd.Next(min, max);
return newNum;
}
Passing through a list of the numbers that you have created so far
You probably won't need this, but just to show a method of unique random number generation with no duplicate check:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var randoms = GenerateRandoms(10, 1, 10).OrderBy(v => v);
foreach (var random in randoms)
{
Console.WriteLine(random);
}
Console.ReadLine();
}
private static int[] GenerateRandoms(int randomCount, int min, int max)
{
var length = max - min + 1;
if (randomCount > length) { throw new ArgumentException($"Cannot generate {randomCount} random numbers between {min} and {max} (inclusive)."); }
var values = new List<int>(length);
for (var i = 0; i < length; i++)
{
values.Insert(i, min + i);
}
var randomGenerator = new Random();
var randoms = new List<int>();
for (var i = 0; i < randomCount; i++)
{
var val = randomGenerator.Next(0, values.Count);
randoms.Add(values[val]);
values.RemoveAt(val);
}
return randoms.ToArray();
}
}
}

Eliminate duplicates from array c#

I'm making a basic Deal or No Deal game, in doing so I have to pick 10 finalists from an array, at random, without repeats.
I have my structure and arrays set out like this
public struct People
{
public string firstname;
public string lastname;
public int age;
}
class Program
{
public static People[] People1 = new People[40];
public static People[] Finalists1 = new People[10];
public static People[] Finalist1 = new People[1];
And my finalists method set out like this
Random rand = new Random();
for (int i = 0; i < Finalists1.Length; i++)
{
num = rand.Next(0, People1.Length);
Finalists1[i].lastname = People1[num].lastname;
Finalists1[i].firstname = People1[num].firstname;
Finalists1[i].age = People1[num].age;
}
How can I eliminate duplicate entries, while maintaining 10 people in the array?
Since initial array doesn't contain duplicates, you can sort it in random order and pick up 10 top items:
Finalists1 = People1
.OrderByDescending(item => 1) // if people have some points, bonuses etc.
.ThenBy(item => Guid.NewGuid()) // shuffle among peers
.Take(10) // Take top 10
.ToArray(); // materialize as an array
If people are selected to the final are not completely random (e.g. contestant can earn points, bonuses etc.) change .OrderByDescending(item => 1), e.g.
.OrderByDescending(item => item.Bonuses)
If you don't want to use Linq, you can just draw Peoples from urn without returning:
private static Random random = new Random();
...
List<People> urn = new List<People>(People1);
for (int i = 0; i < Finalists1.Length; ++i) {
int index = random.Next(0, urn.Count);
Finalists1[i] = urn[index];
urn.RemoveAt(index);
}
You can hold a list or hash set of numbers you have already drawn. Then just roll the dice again to get another random number.
Random rand = new Random();
HashSet<int> drawnNumbers = new HashSet<int>();
for (int i = 0; i < Finalists1.Length; i++)
{
do
{
num = rand.Next(0, People1.Length);
}
while (drawnNumbers.Contains(num));
Finalists1[i] = People1[num];
}
You can change the type of Finalists1 to a HashSet, that does not allow duplicates.
Then change your loop to
while(Finalists1.Length < 10)
{
// random pick from array People1 (you don't need to create a new one)
num = rand.Next(0, People1.Length);
var toAdd = People1[num];
// add to hash-set. Object won't be added, if already existing in the set
Finalists1.Add(toAdd);
}
You probably need to override the Equals method of class People, if you really need to create a new object to add to the hash-set.
You can group people array and select distinct that way.
If you use List you can remove person from the list
`var peopleArray = new People[40];
var peopleCollection = peopleArray.GroupBy(p => new { p.age, p.firstname, p.lastname }).Select(grp => grp.FirstOrDefault()).ToList();
var finalists = new People[10];
var rand = new Random();
for (var i = 0; i < finalists.Length; i++)
{
var index = rand.Next(0, peopleCollection.Count);
var person = peopleCollection[index];
finalists[i].lastname = person.lastname;
finalists[i].firstname = person.firstname;
finalists[i].age = person.age;
peopleCollection.Remove(person);
}
shuffle and take the first 10, for example
People1.Shuffle();
Finalists1= People1.Take(10).ToArray();
you can find shuffle code from StackOverflow or search for "Fisher-Yates shuffle C#" Below methods are taken from This SO Post. Read the answers for more information on why GUID is not used etc..
public static class ThreadSafeRandom
{
[ThreadStatic] private static Random Local;
public static Random ThisThreadsRandom
{
get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); }
}
}
static class MyExtensions
{
public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
}
Swap each selected element in People1 to with the end of the array, and decrement an end-of-array index so that you're only selecting from what's left on the next iteration.
People tempPerson = new People;
int lastElem = People1.length - 1;
for (int i = 0; i < Finalists1.Length; i++)
{
num = rand.Next(0, lastElem + 1);
Finalists1[i] = People1[num];
//swap last entry in People1 with People1[num]
tempPerson = People1[num];
People1[num] = People1[lastElem];
People1[lastElem] = tempPerson;
lastElem--;
}
Sorry if there's a syntax error, I'm mostly using Java and C# these days.
BTW You don't have to set the fields individually since each array stores objects of type Person.

How to minus data length inside the index of a list, if the index is an array?

Well, first of all, I am not sure whether my title in this question delivered what I want to ask or not. I just do not sure how to describe my problem in one sentence, hopefully the title would not cause any misleading.
If I have a list. Inside the list contain 100 data : list<100>
If I put this list inside a 1 second timer tick and do like this:
myList.RemoveRange(0, 2);
This mean, every 1 second, the data length inside the list will be -2;
This mean, every 1 second, it will be <98> , <96> , <94> .... <0>
Now my problem is...I still have a list, but the list will contain an array: list<array[100]>
Now, what I want is, every 1 second, the data length inside the array inside the list will be -2. But I am not sure know how to do this...
what I want is, every 1 second <array[98]> , <array[96]> , <array[96]> ... <array[0]>
And so, if the list contain <array0[100] , array1[100], array2[100]>
if i put this list inside a loop, every 1 second, it should be
array0[98] , array0[96] ... array0[0]
array1[98] , array1[96] ... array1[0]
array2[98] , array2[96] ... array2[0]
Update:
List<int[]> myList = new List<int[]>();
object myLock = new object();
Random rand = new Random();
public Form1()
{
timer1second.Start();
}
private void SomeMethod()
{
int[] myData = new int [100]
for (int i = 0; i < 100; i++)
{
//generate some random number to store inside myData[]
myData[i] = rand.Next(1 , 10);
}
lock (myLock)
{
myList.Add(myData); //mean List[0] = myData[100]
}
}
private void timer1second_Tick(object sender, EventArgs e)
{
lock (myLock)
{
//do something here in myList to get the myData[100 - 2]
//so that every 1 second tick, the data length inside the MyData will be -2
}
}
Convert the Array item into a List.
Then remove the range from the List
Convert it back to an Array.
Insert it back into the List
Here is a sample:
int currentIndex = 0;
var myList = new List<int[]>();
var intArray = new int[100];
myList.Add(intArray);
// Convert to List.
var newIntArrayList = myList[currentIndex].ToList();
// Remove the ranges
// Index would be based on you logic
newIntArrayList.RemoveRange(0, 2);
//Replace the list with the new arry
myList[currentIndex] = newIntArrayList.ToArray();
Update : Array.Resize should also help.
int currentIndex = 0;
int arrayLength = 100;
var myList = new List<int[]>();
var intArray = new int[100];
myList.Add(intArray);
// Get the array
var array = myList[currentIndex];
// Resize
Array.Resize(ref array, arrayLength-2);
//Replace the list with the update array
myList[currentIndex] = array;
List<int> myList = new List<int>();
for (int i = 1; i < 101; i++)
{
myList.Add(i);
}
for (int i = 100; i > 0; i--)
{
System.Threading.Threading.Sleep(1000);
myList.RemoveAt(i);
i -= 1;
myList.RemoveAt(i);
}
Resizing lists and arrays is an expensive operation. Would you consider a custom data structure for your needs with convinient interface and optimized underlying structure? So every tick you will only increment and integer value representing offset:
class Data
{
const int Step = 2;
List<int[]> data;
List<int> cursors;
public Data()
{
data = new List<int[]>();
}
public void AddArray(int[] array)
{
data.Add(array);
cursors.Add(array.Length);
// or cursors.Add(0), depending on your needs
}
public void Tick()
{
for (int i = 0; i < cursors.Count; i++)
{
cursors[i] -= Step;
// or cursors[i] += Step, depending on your needs
}
}
public IEnumerable<int> GetValuesAtIndex(int index)
{
for (int i = 0, i < data[index].Length; i++)
{
if (i > cursors[index]) // or i < cursors[index]
{
yield return data[index][i];
}
}
}
}

Sort a collection of randomly generated numbers

I am creating a random number generator in c#
I generate the numbers as so
Random RandomClass = new Random();
Num1.text = RandomClass.Next(1,49).ToString();
Num2.text = RandomClass.Next(1,49).ToString();
Num3.text = RandomClass.Next(1,49).ToString();
Num4.text = RandomClass.Next(1,49).ToString();
Num5.text = RandomClass.Next(1,49).ToString();
Num6.text = RandomClass.Next(1,49).ToString();
The user clicks a button and the numbers are generated, what I want is for there to be a button which can sort the numbers, so for example smallest to lowest.
Could I turn the numbers generated into an array and call .ToArray and then sort from there? I am unsure how to group the random numbers together to then call a sorting method on them.
Just add the random numbers to a list and sort them.
Random RandomClass = new Random();
List<int> list = new List<int>();
for (int i = 0; i < 10; i++)
list.Add(RandomClass.Next(1, 49));
list.Sort();
// If you need to reverse it...
list.Reverse();
If you are comparing to a List<string> you will need to write a comparer.
Example:
private static int CompareValues(string x, string y)
{
if (x == null)
return y == null ? 0 : -1;
else
{
if (y == null)
return 1;
else
{
int left = Int32.Parse(x);
int right = Int32.Parse(y);
if (left > right)
return 1;
else if (left < right)
return -1;
else
return 0;
}
}
}
Then to use it, pass it as argument to the Sort() method. This will now be used as a custom compare to handle the integer values and sort them properly.
list.Sort(CompareValues);
If you store the random numbers in a list, you could sort (or manipulate them in a number of ways) easily using Linq. Assuming your method returns random integers:
var myRandomNumbers = new List<int>
{
RandomClass.Next(1,49),
RandomClass.Next(1,49)
};
var mySortedRandomNumbers = myRandomNumbers.OrderByDescending(x => x).ToList();
Of course, if you're always calling RandomClass.Next(1,49) you could optimize with a loop and use .Add() on the list.
Here's a solution that generates random numbers and saves them for later.
//fields
private readonly Random _random = new Random();
private readonly List<int> _randomNumbers = new List<int>();
public void SomeEvent(object sender, EventArgs e)
{
_randomNumbers.Clear();
Num1.text = GetRandom().First().ToString();
Num2.text = GetRandom().First().ToString();
Num3.text = GetRandom().First().ToString();
Num4.text = GetRandom().First().ToString();
Num5.text = GetRandom().First().ToString();
Num6.text = GetRandom().First().ToString();
}
public void SortRandomNumbers(object sender, EventArgs e)
{
var sortedRandoms = _randomNumbers;
sortedRandoms.Sort();
//do stuff with sortedRandoms
}
// Gets a random value and caches it
private IEnumerable<int> GetRandom()
{
while(true)
{
var value = _random.Next(1, 49);
_randomNumbers.Add(value);
yield return _randomNumbers.Last();
}
}
If you always have six fields Num1 - Num6, you could add their content to a List<int>, sort them by using .OrderBy() and fill them up again using the ordered list.
List<int> nums = new List<int>();
nums.Add(Convert.ToInt32(Num1.text));
.
.
nums.Add(Convert.ToInt32(Num6.text));
nums = nums.OrderBy(num => num).ToList(); //or OrderByDescending
Num1.text = nums[0];
.
.
Num6.text = nums[5];
Yes, you could use an Array:
RandomClass.Next(1,49).ToString();
ArrayList numbers = new ArrayList();
for (int i = 0; i < 10; i++)
numbers[i] = RandomClass.Next(1,49).ToString();
numbers.Sort();

Categories

Resources