C#, List Instantiation from existing List? - c#

I'm trying to figure out what is happening in the code snippet below.
In the new list instantiation, it look's like they are referencing the other coins List? I have never seen this before, what is the purpose? Sorry if this has already been answer, if so please redirect me. Thank you for your help.
class Program
{
static void Main(string[] args)
{
List<int> coins = new List<int>();
List<int> amounts = new List<int>() { 1, 5, 10, 25, 50 };
Change(coins, amounts, 0, 0, 51);
Console.ReadKey();
}
static void Change(List<int> coins, List<int> amounts, int highest, int sum, int goal)
{
if (sum == goal)
{
Display(coins, amounts);
return;
}
if (sum > goal)
{
return;
}
foreach (int value in amounts)
{
if (value >= highest)
{
List<int> copy = new List<int>(coins); // <<<<<<<
copy.Add(value);
Change(copy, amounts, value, sum + value, goal);
}
}
}
static void Display(List<int> coins, List<int> amounts)
{
foreach (int amount in amounts)
{
int count = coins.Count(value => value == amount);
Console.WriteLine("{0}: {1}",
amount,
count);
}
Console.WriteLine();
}
}

Here's a description of what the lines do.
List<int> copy = new List<int>(coins); // Creates a new list, initializing the values with the values in coins (creating a copy of coins).
copy.Add(value); // adds additional value to the copy.

From the MSDN documentation https://msdn.microsoft.com/en-us/library/fkbw11z0(v=vs.110).aspx :
List Constructor (IEnumerable)
Initializes a new instance of the List class that contains elements copied from the specified collection and has sufficient capacity to accommodate the number of elements copied.
List<int> copy = new List<int>(coins); // They are creating a copy of the list `coins`, called `copy`.

Related

Random method return two values without duplicate

I created two methods that take random values from database table
This method will return an integer random value
private int GetDayValue()
{
Random rnd = new Random();
List<int> days = GetDays();
int r = rnd.Next(days.Count);
return days[r];
}
This method will return also an integer random value
private int GetPeriodValue(string grd_id)
{
Random rnd = new Random();
List<int> periods = GetPeriods(grd_id);
int r = rnd.Next(periods.Count);
return periods[r];
}
Here there is a for loop will take random value from two methods
for (int z = 0; z <= secPortion; z++)
{
//here the random value of day
day = GetDayValue();
//here the random value of period
period = GetPeriodValue(grd_id);
//this method will insert the value on database table
SetFirstShot(teacher, sub, sec, period, day);
}
My question:
I want to create method will return random value of day and period together for example random value (ex: 3,5 ... 4,6 .... 1,1) and not repeated during the loop for example 4,6 will generated once time then another random value but if it 4,6 the method will create again a random value.
You can use a hash function instead that has a good random distribution aspect to it. A hash function with return the same value for the same inputs each time, while the results will "seem" random, which might be all the "randomness" you need.
using System;
using System.IO;
using System.Security.Cryptography;
// ...
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
using (var hash = MD5.Create())
{
writer.Write(day);
writer.Write(period);
var data = md5Hash.ComputeHash(stream.ToArray());
var randomNumber = BitConverter.ToInt32(data);
}
The added benefit is that you don't have to store previously-computed values in any sort of database. Any two agents with the same hashing algorithm will generate the same hashes. The values may not be completely unique, but they should vary wildly from input to input while also being deterministic with no hidden state. Truly unique would require querying outside state and probably introduce race conditions if your system is distributed.
It appears that GetDays() and GetPersiodValue() returns two int lists, so I'm writing two mock methods for those.
static List<int> GetDays()
{
return new List<int>() { 1, 2, 3, 4, 5, 6, 7 };
}
static List<int> GetPeriods()
{
return new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
}
First thing you need to do is move the new Random() out of the methods (so that it's outside the loop). Otherwise when you iterate so fast it will keep giving you the same number.
static int GetRandomDay(Random rnd)
{
var days = GetDays();
return days[rnd.Next(days.Count)];
}
static int GetRandomPeriod(Random rnd)
{
var periods = GetPeriods();
return periods[rnd.Next(periods.Count)];
}
Then I'll do something like this to see if the generated pair of random values were generated before. Add to a list (or DB in your case) if not.
static void Main(string[] args)
{
var RandomList = new List<Tuple<int, int>>();
Random rnd = new Random();
for (int i =0; i < 10; i++)
{
bool isUnique = false;
do
{
int day = GetRandomDay(rnd);
int period = GetRandomPeriod(rnd);
if(RandomList.Where(x => x.Item1 == day && x.Item2 == period).FirstOrDefault() == null)
{
RandomList.Add(new Tuple<int, int>(day, period));
isUnique = true;
}
} while (!isUnique);
}
Console.ReadLine();
}
I tried to use KeyValuePair and I solved, its works well !
Here the code that I used:
// I created a list contain two pairs..
List<KeyValuePair<int, int>> dictionary = new List<KeyValuePair<int, int>>();
for (int z = 0; z < secPortion; z++)
{
day = GetDayValue();
period = GetPeriodValue(grd_id);
//here I pass the value of day and period to the pairs
KeyValuePair<int, int> myItem = new KeyValuePair<int, int>(day, period);
//here I created a list which is the list of values for the random key, if it is exist or not.
List<int> values = (from kvp in dictionary where kvp.Key == day select kvp.Value).ToList();
// this is a bool variable its value by default is true, once there is a duplicated value it will be changed to false....
bool FirstChecker = true;
if (values.Contains(period))
{
FirstChecker = false;
z--;
}
else
{
dictionary.Add(myItem);
SetFirstShot(teacher, sub, sec, period, day);
}
}
I think this is what you need.
Although the example is a solution for a one-dimensional array, actually in your case the two list days and periods can be mapped to one sequence whose length is days.Count * periods.Count. Or you can do this for each list separately but some cases will be missed.

Max value function for an array

I have read in a file, sorted the file by into three columns and put all of the data in each columns into 3 arrays. I now need to make a method to get the max value out of the second column array. This is the code:
static void Main(string[] args)
{
string file1 = System.IO.File.ReadAllText(#"C:\file1.txt");
List<double> Array1 = new List<double>();
List<double> Array2 = new List<double>();
List<double> Array3 = new List<double>();
IEnumerable<string> lines = File.ReadLines(#"C:\File1.txt");
foreach (string line in lines)
{
string[] columns = line.Split(',');
if (columns.Length != 3)
{
continue; // skips this line
}
Array1.Add(Convert.ToDouble(columns[0]));
Array2.Add(Convert.ToDouble(columns[1]));
Array3.Add(Convert.ToDouble(columns[2]));
}
Console.WriteLine(Max(Array1.ToArray()));
}
static double Max (double[] x)
{
double maxValue = x.Max();
return maxValue;
}
ERROR: Type or namespace definition, or end-of-file expected.
I need to fix the Max Method and also I do not know how to Say that it is Array 2 that we need to get the max value of. I then need to go back up to the main and Use the Max Method to get the maximum value of array 2. Clearly their are beginners errors in the Max function but I have researched the problem andI am unsure of how to proceed.
static double Max (double[] x)
{
double[] x // This line shouldn't be here
double maxValue = x.Max();
return maxValue;
}
You're declaring double[] x twice, in the parameter as well as in the method. This will mess things up.
Also, try not to have the same name for your method as the one from the API, just to make code easier to read.
Lastly, you never called the method from main. :P
namespace Your_Name_Space
{
class Your_Program
{
public static void Main(string[] args)
{
string file1 = System.IO.File.ReadAllText(#"D:\file1.txt");
List<double> Array1 = new List<double>();
List<double> Array2 = new List<double>();
List<double> Array3 = new List<double>();
IEnumerable<string> lines = File.ReadLines(#"D:\File1.txt");
foreach (string line in lines)
{
string[] columns = line.Split(',');
if (columns.Length != 3)
{
continue; // skips this line
}
Array1.Add(Convert.ToDouble(columns[0]));
Array2.Add(Convert.ToDouble(columns[1]));
Array3.Add(Convert.ToDouble(columns[2]));
}
Console.WriteLine(Max(Array1.ToArray()));
Console.ReadKey();
}
public static double Max(double[] x)
{
double maxValue = x.Max();
return maxValue;
}
}
}
file1.text's content is like below :
1, 2, 3
4, 5, 6
7, 8, 9
All your codes ran. When the above code is compiled and executed, it produces the following result:
7
'end-of-file expected' error's reason is braces excess. You should control your braces. And value 7 isn't second coloumn.

System.Array does not contain definition for Add

I am creating a blackjack game and so far I have made a card class, deck class and shoe class. The card class works the deck class works, the shoe class works but I am still working on my hand class. I created a method that throws an exception if there are already MAX_CARDS cards in the hand otherwise it adds the card to the hand and increments _cardCount but for some reason on my code _hand.Add(card) says that
System.Array does not contain a definition for Add.
Any help or guidance in the right direction would be appreciated
Here's what I have for my hand class
class Hand
{
const Int32 MAX_CARDS = 12;
private Card[] _hand = new Card[MAX_CARDS];
private Int32 _cardCount = 0;
public Int32 CardCount
{
get
{
return _cardCount;
}
}
public void AddCard(Card card)
{
if (_cardCount >= MAX_CARDS)
{
throw new Exception("Cannot of more than 12 cards in a hand");
}
else
{
_hand.Add(card);
_cardCount++;
}
}
public Card GetCard(Int32 cardIndex)
{
if (cardIndex >= _cardCount)
{
throw new Exception("Invalid Entry");
}
else
{
return _hand[cardIndex];
}
}
Int32[] cardValues = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10 };
String[] cardSymbols = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
private Int32 SymbolToValue(String symbol)
{
int index = Array.IndexOf(cardSymbols, symbol);
if (index != -1)
{
return cardValues[index];
}
else
{
throw new Exception("Value Not In Table");
}
}
public Int32 GetSum()
{
int value = 0;
Boolean aceflag;
for (int i = 0; i < _hand.Length; i++)
{
value += SymbolToValue(_hand[i].Value);
if (String.Equals(_hand[i].Value, "A"))
{
aceflag = true;
}
else
{
aceflag = false;
}
if (aceflag == true && value <= 21)
{
value = value + 10;
}
}
return value;
}
}
An Array's size in c# is immutable so I would suggest using a List instead.
private List<Card> _hand = new List<Card>(MAX_CARDS);
I think your code has a lot of problems, but if you really want to do it the way you're doing it, use the index to add an item:
public void AddCard(Card card)
{
if (_cardCount >= MAX_CARDS)
{
throw new Exception(string.Format("This hand already contains {0} cards, " +
"which is the maximum.", MAX_CARDS));
}
else
{
_hand[_cardCound] = card;
_cardCount++;
}
}
enter code here we create a new List with the elements in an array that already exists. We use the List constructor and pass it the array. List receives this parameter and fills its values from it.
Caution:The array element type must match the List element type or compilation will fail.
Program that copies array to List: C#
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
int[] arr = new int[3]; // New array with 3 elements
arr[0] = 2;
arr[1] = 3;
arr[2] = 5;
List<int> list = new List<int>(arr); // Copy to List
Console.WriteLine(list.Count); // 3 elements in List
}
}
Output : 3
Array is not good for your code in c# list is used array is not a good option. So use list type data. You can use list and store every type data in this object and convert it in any type and you can also get single data from list using a loop. It so easy to use it and implement so use list it good and easy for code .
First, we declare a List of int values. We create a new List of unspecified size and adds four prime numbers to it. Values are stored in the order added. There are other ways to create Lists—this is not the simplest.
using System.Collections.Generic;
class Program
{
static void Main()
{
List<int> list = new List<int>();
list.Add(2);
list.Add(3);
list.Add(5);
list.Add(7);
}
}

Adding to a range of generic lists in c#

Anyone know of a way to add a value to a range of generic lists in c#?
I'm currently building up a large List<List<int>> and the whole process is taking too long and I'm trying to avoid using foreach loops and nested foreach loops in order to shave some time off.
Lets say I had 600 rows in a generic list. For each of the first 200 rows, I'd like to add a "1". For the next 200, I'd like to add a "2". For the next 200, I'd like to add a "3".
The way I'm doing that now, I have to loop through it 600 times and add each one individually, whereas what I'd like to do is loop through it 3 times and add the entries in bulk.
The code I was hoping for would be something like:
List<List<int>> idList = GetFullList(); //list contains 600 rows
int[] newItems = {1, 3, 5};
int count = 0;
int amountToAmend = 200;
foreach (int i in newItems)
{
//List<int> newID = new List<int>();
//newID.Add(i);
(idList.GetRange(count, amountToAmend)).Add(i);
count += amountToAmend;
}
Obviously this doesn't work, but hopefully you can see the kind of thing I'm going for. In my application I'm currently needing to do tens of thousands of unnecessary loops, when often less than 10 could feasibly do the job if the code exists!
UPDATE: I'm not sure I've explained this well, so just to clarify, here are the results I'm looking for here
If I have a list with 6 rows like so:
[6,7,8]
[5,6,7]
[6,4,8]
[2,4,7]
[5,1,7]
[9,3,5]
i know that I'd like to add a 1 to the first 3 rows and a 2 to the next 3 rows, so they would become:
[6,7,8,1]
[5,6,7,1]
[6,4,8,1]
[2,4,7,2]
[5,1,7,2]
[9,3,5,2]
This is easy to do with foreach loops and is how I currently do it, but because of the sheer volume of data involved, I'm looking for ways to cut the time taken on specific functions. I'm not sure if a way exists tbh, but if anyone knows, then it'll be the good people of Stack Overflow :)
You may use Skip and Take methods from LINQ.
like idList.Skip(0).Take(200) it will give you first 200 items from your list, then you may update these items.
For update you may say:
int increment=2;
list.Select(intVal=> intVal+increment).ToList();
How about this:
foreach (int i in newItems)
{
foreach (var row in idList.Skip(count).Take(amountToAmend))
{
row.Add(i);
}
count += amountToAmend;
}
Or with a for-loop:
foreach (int i in newItems)
{
for (int j = 0; j < amountToAmend; j++)
{
idList[count + j].Add(i);
}
count += amountToAmend;
}
You want to have amountToAmend times each item in newItems ?
Like :
200 times 1
200 times 3
200 times 5
If so, you can try :
int amountToAmend = 200;
List<int> newItems = new List<int>(){ 1, 3, 5 };
<List<int>> idList = new List<List<int>>();
newItems.ForEach(i => idList.Add(new List<int>(Enumerable.Repeat(i, amountToAmend))));
List<List<int>> idList = GetFullList(); //list contains 600 rows
var iterator = idList.Begin();
int[] newItems = {1, 3, 5};
int count = 0;
int amountToAmend = 200;
foreach (var item in newItems)
{
iterator = iterator.AddItem(item);
iterator = iterator.MoveForward(amountToAmend);
}
public struct NestedListIterator<T>
{
public NestedListIterator(List<List<T>> lists, int listIndex, int itemIndex)
{
this.lists = lists;
this.ListIndex = listIndex;
this.ItemIndex = itemIndex;
}
public readonly int ListIndex;
public readonly int ItemIndex;
public readonly List<List<T>> lists;
public NestedListIterator<T> AddItem(T item)
{
var list = lists.ElementAtOrDefault(ListIndex);
if (list == null || list.Count < ItemIndex)
return this;//or throw new Exception(...)
list.Insert(ItemIndex, item);
return new NestedListIterator<T>(this.lists, this.ListIndex, this.ItemIndex + 1);
}
public NestedListIterator<T> MoveForward(List<List<T>> lists, int index)
{
//if (index < 0) throw new Exception(..)
var listIndex = this.ListIndex;
var itemIndex = this.ItemIndex + index;
for (; ; )
{
var list = lists.ElementAtOrDefault(ListIndex);
if (list == null)
return new NestedListIterator<T>(lists, listIndex, itemIndex);//or throw new Exception(...)
if (itemIndex <= list.Count)
return new NestedListIterator<T>(lists, listIndex, itemIndex);
itemIndex -= list.Count;
listIndex++;
}
}
public static int Compare(NestedListIterator<T> left, NestedListIterator<T> right)
{
var cmp = left.ListIndex.CompareTo(right.ListIndex);
if (cmp != 0)
return cmp;
return left.ItemIndex.CompareTo(right.ItemIndex);
}
public static bool operator <(NestedListIterator<T> left, NestedListIterator<T> right)
{
return Compare(left, right) < 0;
}
public static bool operator >(NestedListIterator<T> left, NestedListIterator<T> right)
{
return Compare(left, right) > 0;
}
}
public static class NestedListIteratorExtension
{
public static NestedListIterator<T> Begin<T>(this List<List<T>> lists)
{
return new NestedListIterator<T>(lists, 0, 0);
}
public static NestedListIterator<T> End<T>(this List<List<T>> lists)
{
return new NestedListIterator<T>(lists, lists.Count, 0);
}
}
There is no builtin function, although you cannot avoid looping(explicit or implicit) at all since you want to add a new element to every list.
You could combine List.GetRange with List.ForEach:
var newItems = new[] { 1, 2 };
int numPerGroup = (int)(idList.Count / newItems.Length);
for (int i = 0; i < newItems.Length; i++)
idList.GetRange(i * numPerGroup, numPerGroup)
.ForEach(l => l.Add(newItems[i]));
Note that above is not Linq and would work even in .NET 2.0
This is my old approach which was not what you needed:
You can use Linq and Enumerable.GroupBy to redistribute a flat list into nested lists:
int amountToAmend = 200;
// create sample data with 600 integers
List<int> flattened = Enumerable.Range(1, 600).ToList();
// group these 600 numbers into 3 nested lists with each 200 integers
List<List<int>> unflattened = flattened
.Select((i, index) => new { i, index })
.GroupBy(x => x.index / amountToAmend)
.Select(g => g.Select(x => x.i).ToList())
.ToList();
Here's the demo: http://ideone.com/LlEe2

access the value of a random element of an list c#

I'm trying to access the value of a random element of an list. At the moment my code seems to be returning the element rather than the value.
int x = _randMoveDecider.Count;
//makes sure x is never more than the array size
if(x != 0)
{
x = x - 1 ;
}
Random _r = new Random();
_move = _r.Next(_randMoveDecider[x]);
return _randMoveDecider[_move];
at the moment if _randMoveDecider holds the values 2, 5 and 9 it will return 0, 1 or 2 rather than the values in the list, where am I going wrong?
[edit] I guess I should have said, the length of _randMoveDecider and the values stored in it change with each run through of the program, but they are always integers.
How about just this?
// as a field somewhere so it's initialised once only
public Random _r = new Random();
// later in your code
var _randList = new List<int>{4,5,8,9};
var _move = _r.Next(_randList.Count);
return _randList[_move];
Even better, here's something that will randomise any list:
public static Random _rand = new Random();
public IEnumerable<T> Randomise<T>(IList<T> list)
{
while(true)
{
// we find count every time since list can change
// between iterations
yield return list[_rand.Next(list.Count)];
}
}
One way of using it in your scenario:
// make this a field or something global
public IEnumerbale<int> randomiser = Randomise(_randList);
// then later
return randomiser.First();
Firstly you should initialize Random once. Make it a field:
private Random _rand = new Random();
Then get a random number from the proper range. if(x!=0) is useless - Next() returns numbersform <0, n) range
return _randMoveDecider[_rand.Next(_randMoveDecider.Count)];
Simply add this extension class inside main class:
public static class Extensions
{
public static int randomOne(this List<int> theList)
{
Random rand = new Random(DateTime.Now.Millisecond);
return theList[rand.Next(0, theList.Count)];
}
}
and then call it:
int value = mylist.randomOne();
EDIT: This is a test program that demonstrates how one would use the method. Note that due to incorrect usage of Random it produces very unbalanced results with more than 50 "random" numbers out of 100 being the same.
class Program
{
static void Main(string[] args)
{
var myList = Enumerable.Range(0, 100).ToList();
var myRandoms = myList.Select(v => new { key = v, value = 0 })
.ToDictionary(e => e.key, e => e.value);
for (int i = 0; i < 100; i++)
{
var random = myList.RandomOne();
myRandoms[random]++;
}
Console.WriteLine(myRandoms.Values.Max());
Console.ReadLine();
}
}
To fix the issue make Random static instance for Extension class or share more broadly in the program. This is discussed in FAQ for Random.
public static class Extensions
{
static Random rand = new Random();
public static int randomOne(this List<int> theList)
{
return theList[rand.Next(0, theList.Count)];
}
}
var random = new Random();
var item = list.ElementAt(random.Next(list.Count()));

Categories