Auto-initializing C# lists - c#

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

Related

How define a string array list?

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"}};

How to get unique record in list [duplicate]

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

How do I bind a jagged array of strings to a DataGrid in C#?

I have a jagged array of strings in C#.
How do I bind it to a DataGrid such that I can see the contents of the array?
Currently in the DataGrid, instead of the array's contents, I see a column that says "Length", "Long Length", "Rank", "SyncRoot", etc...basically, properties of the array and not the contents of the array.
My code:
string[][] jagged = new string [100][];
//...jagged array is populated...
dataGridView1.DataSource = jagged;
Here is an example that you can try following I didn't do this with String[] but you can get the Idea
//
// 1. Create two dimensional array
//
const int dim = 1000;
double[,] array = new double[dim,dim];
Random ran = new Random();
for(int r = 0; r < dim; r++)
{
for(int c = 0; c < dim; c++)
{
array[r,c] = (ran.Next(dim)); // fill it with random numbers.
}
}
// 2. Create ArrayDataView class in which
// constructor you pass the array
// and assign it to DataSource property of DataGrid.
dataGrid1.DataSource = new ArrayDataView(array);
For String[][] here is an example
string[][] arr = new string[2][];
arr[0] = new String[] {"a","b"};
arr[1] = new String[] {"c","d"};
DataGrid1.DataSource = arr[0];
DataGrid1.DataBind();//The result is: a,b in datagrid
using LinQ look at this
List<string> names = new List<string>(new string[]
{
"John",
"Frank",
"Bob"
});
var bindableNames =
from name in names
select new {Names=name};
dataGridView1.DataSource = bindableNames.ToList();
USING LINQ for Multi Denensional Array
string[][] stringRepresentation = ds.Tables[0].Rows
.OfType<DataRow>()
.Select(r => ds.Tables[0].Columns
.OfType<DataColumn>()
.Select(c => r[c.ColumnName].ToString())
.ToArray())
.ToArray();
As given by the current accepted answer and as mentioned by Michael Perrenoud in the comments, you can use Mihail Stefanov's ArrayDataView classes to achieve this binding. His original code, however, was originally conceived to work only with multidimensional arrays. I have since modified his code to work with jagged arrays as well and made it available through the Accord.NET Framework.
Now, you do not need to use the whole framework for doing that, you can simply use the updated classes available here. After incorporating those classes in your project, all you have to do is
dataGridView.DataSource = new ArrayDataView( yourArray );
I hope this clarification helps.
As I mentioned, I am the author of Accord.NET, but the original credit really goes to Stefanov.

LINQ Update one list from another

I'm trying to find an elegant way of updating values in a ConcurrentDictionary. I've created a quick example of what I'm trying to achieve below:
ConcurrentDictionary<int, MyDataClass> dataLookup = new ConcurrentDictionary<int, MyDataClass>();
// Initialise the example dataLookup with some dummy data
new List<MyDataClass>
{
new MyDataClass { Id = 1, ValueProperty = 0 },
new MyDataClass { Id = 2, ValueProperty = 0 },
new MyDataClass { Id = 3, ValueProperty = 0 },
new MyDataClass { Id = 4, ValueProperty = 0 },
new MyDataClass { Id = 5, ValueProperty = 0 }
}.ForEach(myClass => dataLookup.TryAdd (myClass.Id, myClass));
// incoming results that need to be fed into the above dataLookup
List<MyDataClass> newDataReceived = new List<MyDataClass>
{
new MyDataClass { Id = 1, ValueProperty = 111 },
new MyDataClass { Id = 3, ValueProperty = 222 },
new MyDataClass { Id = 5, ValueProperty = 333 }
};
So in the above example I want to set the ValueProperty in the dataLookup ConcurrentDictionary with the Id of 1, 3 & 5 to 111, 222 and 333 respectively. I can change the newDataReceived object into anything I want but I'm pretty much stuck with the dataLookup as a ConcurrentDictionary.
At the moment I'm iterating through the list but I'm looking for some suggestions on using LINQ to make this task more efficient.
If it's truly just updates that are coming in, you could just use another ForEach:
newDataReceived.ForEach(x => dataLookup[x.Id].ValueProperty = x.ValueProperty);
Personally I would just express this with a simple foreach loop though:
foreach(var update in newDataReceived)
dataLookup[update.Id].ValueProperty = update.ValueProperty;
Note that above is missing a check whether the item is actually contained in the concurrent dictionary - if that is not guaranteed (it's not an update) you would have to add this check.
Just tried to update in Join() and surprised it worked.
You obviously have to implement your own IEqualityComparer in order to compare only required members such as ID, key or similar.
private static void SaveProcessedFile(IEnumerable<HashedRow> processedRows, IEnumerable<HashedRow> justProcessedRows)
{
var comparer = new HashedRowEqualityComparerOrderLine();
var updated = justProcessedRows.Join(processedRows, n => n, o => o, (n, o) => { o = n; return n; }, comparer); // n - new, o - old
var inserted = justProcessedRows.Except(updated, comparer);
// To do something
}
Linq is for querying, not updating. If you were able to create a new dictionary it would be possible by using Linq's ToDictionary() method, but since you have to call a method to add you're more or less relegated to a foreach loop.
Also, Linq wouldn't make anything more efficient, it just makes the code look more natural.

Creating a random name generator. How do I accomplish this?

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.

Categories

Resources