I'm trying to grab a single item from each of the Lists here, and combine them to make a unique name. This is just for kicks. :)
Here are the lists:
List<string> FirstNames = new List<string>()
{
"Sergio",
"Daniel",
"Carolina",
"David",
"Reina",
"Saul",
"Bernard",
"Danny",
"Dimas",
"Yuri",
"Ivan",
"Laura"
};
List<string> LastNamesA = new List<string>()
{
"Tapia",
"Gutierrez",
"Rueda",
"Galviz",
"Yuli",
"Rivera",
"Mamami",
"Saucedo",
"Dominguez",
"Escobar",
"Martin",
"Crespo"
};
List<string> LastNamesB = new List<string>()
{
"Johnson",
"Williams",
"Jones",
"Brown",
"David",
"Miller",
"Wilson",
"Anderson",
"Thomas",
"Jackson",
"White",
"Robinson"
};
I know I get a single item via an index, and I also know that I can use the Random class to generate a random number from 0 to ListFoo.Count.
What I don't know is how to check if a random permutation has already been drawn from the collections.
I've thought about using the tuple class:
List<Tuple<int,int,int>> permutations = new List<Tuple<int,int,int>>();
But I'm having a brainfart here. ;) Any guidance? I'm not really looking for the entire code to this simple problem, just a suggestion or hint.
EDIT
Thanks to the suggestions given here, here what I've come up with. Any room for improvements?
static void Main(string[] args)
{
List<string> FirstNames = new List<string>()
{
"Sergio",
"Daniel",
"Carolina",
"David",
"Reina",
"Saul",
"Bernard",
"Danny",
"Dimas",
"Yuri",
"Ivan",
"Laura"
};
List<string> LastNamesA = new List<string>()
{
"Tapia",
"Gutierrez",
"Rueda",
"Galviz",
"Yuli",
"Rivera",
"Mamami",
"Saucedo",
"Dominguez",
"Escobar",
"Martin",
"Crespo"
};
List<string> LastNamesB = new List<string>()
{
"Johnson",
"Williams",
"Jones",
"Brown",
"David",
"Miller",
"Wilson",
"Anderson",
"Thomas",
"Jackson",
"White",
"Robinson"
};
var permutations = new List<Tuple<int, int, int>>();
List<string> generatedNames = new List<string>();
Random random = new Random();
int a, b, c;
//We want to generate 500 names.
while (permutations.Count < 500)
{
a = random.Next(0, FirstNames.Count);
b = random.Next(0, FirstNames.Count);
c = random.Next(0, FirstNames.Count);
Tuple<int, int, int> tuple = new Tuple<int, int, int>(a, b, c);
if (!permutations.Contains(tuple))
{
permutations.Add(tuple);
}
}
foreach (var tuple in permutations)
{
generatedNames.Add(string.Format("{0} {1} {2}", FirstNames[tuple.Item1],
LastNamesA[tuple.Item2],
LastNamesB[tuple.Item3])
);
}
foreach (var n in generatedNames)
{
Console.WriteLine(n);
}
Console.ReadKey();
}
You are on the right track!
Every time you generate a name, add it to your tuple list
//Create the tuple
Tuple <int, int, int> tuple = new Tuple<int, int, int>(index1, index2, index3)
if(!permutations.Contains(tuple))
{
permutations.Add(tuple);
//Do something else
}
I would think the simplest solution is to just the stuff the assembled name into a HashSet<string> which will ensure the list of created names is unique.
An alternative to the HashSet answer is to build all of the possible combinations in advance, shuffle them, then store them in a Queue, where you can retrieve them one at a time. This will avoid having to check the existing ones every time you build a new one, and will still be random.
This only works if you don't have a large set to begin with, since the work involved in creating the complete list and shuffling it would be huge for a large set of data.
It's really easy to generate them all using LINQ:
var combs =
(from first in FirstNames
from second in LastNamesA
from third in LastNamesB
select new Tuple<string, string, string>(first, second, third)).ToList();
After this, if you need to take unique elements from the list randomly, just shuffle the list and then pick them one-by-one in order.
You can use the Knuth-Fisher-Yates algorithm (that's an in-place shuffle):
Random rand = new Random();
for (int i = combs.Count - 1; i > 0; i--)
{
int n = rand.Next(i + 1);
var mem = combs[i];
combs[i] = combs[n];
combs[n] = mem;
}
I would create a HashSet<int> and store the numeric representation of the picks (eg 135 for first, third and 5th or use 010305) and then check if they are in the set.
Create a new tuple with 3 random digits
Check if permutations contains your new tuple
If not => Add new tuple to the list. If yes, start with point 1 again.
Related
I'd like to define a list whose element is a 3-elements array. Below codes seems ok:
List<dynamic[]> bb = null;
but when I try:
List<dynamic[3]> bb = null;
It throws error. Sure I can create a class/struct for that. But is there a way to define it directly?
Here is one way:
var list = new List<string[]>();
list.Add(new string[3] { "1", "2", "3" });
list.Add(new string[2] { "1", "2" });
Update:
#Ilya's answer shows a solution with dynamic, but I advise you against using dynamic. If you know the structure of the objects create a class or use a tuple, e.g.
var list = new List<(int id, string name, uint reputation)>();
list.Add((298540, "xiaoyafeng", 11));
list.Add((2707359, "Ilya", 3576));
list.Add((581076, "tymtam", 4421));
list.Add((3043, "Joel Coehoorn", 294378));
I'm not sure what your issue was; your title talks about a "string array list", but your posted code describes a list of arrays of dynamic.
I'm not sure I'll ever have reason to create a list of arrays of dynamic, but to show that the code that you discussed in your post can work, this works for me:
var stuff = new List<dynamic[]>
{
new dynamic[] {1, "string"},
new dynamic[] {DateTime.Now, 45.0}
};
But, as noted in other answers, dynamic is a great answer to several classes of questions. But, it's not the right answer here. The right answer to the title of your question (not the description) will use a list of string arrays (as has been pointed in the other answers:
var otherStuff = new List<string[]>
{
new string[] {"Now", "Is", "the", "time"},
new string[] {"for all", "good men, etc."}
};
It seems that you need something like this:
List<dynamic[]> bb = new List<dynamic[]>();
bb.Add(new dynamic[3]); // here you add a 3-element array
bb.Add(new dynamic[3] { "a", "b", "c" }); // here you add another one 3-element array
// List containing a string array with 3 nulls in it
var aa = new List<string[]> {new string[3]};
// List containing a string array with 3 strings in it
var bb = new List<string[]> {new[] {"a", "b", "c"}};
I'm creating a game where I'd like to generate a name for 16 different planets from a bank of names and assign them to a planet. I've created an array for the planets and the name generation logic which are featured below.
Planet[] planetArray = new Planet[16];
public static void NameGeneration()
{
List<String> planetNames = new List<String>()
{
"Bak'hur", "Etonia", "Laurellan",
"Ragki", "Metiope", "Defel",
"Liehne", "Rykhan", "Heito",
"Makha", "Cerbi", "Helios",
"Luruguan", "Chawnos", "T'hig",
"Blana", "Pergate V", "Shemon III",
"Yokteth", "Letry", "Last Besgino",
"Ayus", "Alterus", "Qurenos"
};
List<Tuple<int>> instances = new List<Tuple<int>>();
List<string> generatedNames = new List<string>();
Random random = new Random();
int planetName;
//generating 16 names
while(instances.Count < 16)
{
planetName = random.Next(0, planetNames.Count);
Tuple<int> tuple = new Tuple<int>(planetName);
if (instances.Contains(tuple))
{
instances.Add(tuple);
}
}
foreach (var tuple in instances)
{
generatedNames.Add(string.Format("{0}", planetNames[tuple.Item1]));
}
foreach (var n in generatedNames)
{
}
}
I really don't know where to go from here, though I have considered selecting from the list and assigning it manually, or randomising the planet aswell but I'd still be stuck in my tracks.
Any help or tips would be appreciated. Thank you.
Ryan
I believe this code does same thing - creates list of randomly picked 16 planet names:
var generatedNames = planetNames.OrderBy(n => random.Next()).Take(16).ToList();
You can use Linq to create the planets, after the random. Something like:
planetArray = generatedNames.Select(x=>new Planet(x)).ToArray();
BTW, Why do you use List of Tuple of int?. You can use List directly.
This question already has answers here:
Getting unique items from a list [duplicate]
(5 answers)
Closed 8 years ago.
I have a list of string having currencies in it, for example the size is 1000. I want list if string of all the unique currencies out of 1000 records.
Now its like -
INR
USD
JPY
USD
USD
INR
and I want List of string like -
INR
USD
JPY
only unique record
Preferably without using Linq
EDIT:
I missed the part "preferably without using LINQ",
You may try the following if you are using .Net framework 2.0 or you don't want to use LINQ.
List<string> list = new List<string> { "abc", "abc", "ab", "def", "abc", "def" };
list.Sort();
int i = 0;
while (i < list.Count - 1)
{
if (list[i] == list[i + 1])
list.RemoveAt(i);
else
i++;
}
use Distinct()
List<string> list = new List<string> { "abc", "abc", "ab", "def", "abc","def" };
List<string> uniqueList = list.Distinct().ToList();
The uniqueList will contain 3 items "abc","ab","def"
Remember to include: using System.Linq; at the top
HashSet<T> is what you're looking for. Reference MSDN:
The HashSet<T> class provides high-performance set operations. A set is a collection that contains no duplicate elements, and whose elements are in no particular order.
Note that the HashSet<T>.Add(T item) method returns a bool -- true if the item was added to the collection; false if the item was already present.
HashSet will work for you if using .NET 3.5 or above, no Linq involved.
var hash = new HashSet<string>();
var collectionWithDup = new [] {"one","one","two","one","two","zero"};
foreach (var str in collectionWithDup)
{
hash.Add(str);
}
// Here hash (of type HashSet) will be containing the unique list
If you are not using .NET 3.5, simple use this piece of code:
List<string> newList = new List<string>();
foreach (string s in list)
{
if (!newList.Contains(s))
newList.Add(s);
}
Why not store these in a HashSet and then read out from that. The set will only contain unique values.
Suppose you have these values stored in array or ArrayList there are 2 ways:
first way
var UniqueValues = nonUnique.Distinct().ToArray();
second way
//create a test arraylist of integers
int[] arr = {1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, 7, 7, 8, 8, 9, 9};
ArrayList arrList = new ArrayList(arr);
//use a hashtable to create a unique list
Hashtable ht = new Hashtable();
foreach (int item in arrList) {
//set a key in the hashtable for our arraylist value - leaving the hashtable value empty
ht.Item[item] = null;
}
//now grab the keys from that hashtable into another arraylist
ArrayList distincArray = new ArrayList(ht.Keys);
You can create your own Distinct Extension Method:
public static class ExtensionMethods
{
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> list)
{
var distinctList = new List<T>();
foreach (var item in list)
{
if (!distinctList.Contains(item)) distinctList.Add(item);
}
return distinctList;
}
}
Now you can do this:
static void Main(string[] args)
{
var list = new List<string>() {"INR", "USD", "JPY", "USD", "USD", "INR"};
var distinctList = list.Distinct();
foreach(var item in distinctList) Console.WriteLine(item);
}
Which will yield:
INR
USD
JPY
Let's say I have following code:
List<string> numbers = new List<string> { "1", "2" };
List<string> numbers2 = new List<string> { "1", "2"};
if (numbers.Equals(numbers2))
{
}
Like you can see I have two lists with identical items. Is there a way to check if these two lists are equal by using one method?
SOLUTION:
Use SequenceEqual()
Thanks
Use Enumerable.SequenceEqual, but Sort the lists first.
// if order does not matter
bool theSame = numbers.Except(numbers2).Count() == 0;
// if order is matter
var set = new HashSet<string>(numbers);
set.SymmetricExceptWith(numbers2);
bool theSame = set.Count == 0;
I am creating a new C# List (List<double>). Is there a way, other than to do a loop over the list, to initialize all the starting values to 0?
In addition to the functional solutions provided (using the static methods on the Enumerable class), you can pass an array of doubles in the constructor.
var tenDoubles = new List<double>(new double[10]);
This works because the default value of an double is already 0, and probably performs slightly better.
You can use the initializer:
var listInt = new List<int> {4, 5, 6, 7};
var listString = new List<string> {"string1", "hello", "world"};
var listCustomObjects = new List<Animal> {new Cat(), new Dog(), new Horse()};
So you could be using this:
var listInt = new List<double> {0.0, 0.0, 0.0, 0.0};
Otherwise, using the default constructor, the List will be empty.
Use this code:
Enumerable.Repeat(0d, 25).ToList();
new List<double>(new double[25]); //Array elements default to 0
One possibility is to use Enumerable.Range:
int capacity;
var list = Enumerable.Range(0, capacity).Select(i => 0d).ToList();
Another is:
int capacity;
var list = new List<double>(new double[capacity]);
A bit late, but maybe still of interest:
Using LINQ, try
var initializedList = new double[10].ToList()
...hopefully avoiding copying the list (that's up to LINQ now).
This should be a comment to Michael Meadows' answer, but I'm lacking reputation.
For more complex types:
List<Customer> listOfCustomers =
new List<Customer> {
{ Id = 1, Name="Dave", City="Sarasota" },
{ Id = 2, Name="John", City="Tampa" },
{ Id = 3, Name="Abe", City="Miami" }
};
from here: David Hayden's Blog