other way to add item to List<> - c#

In my other question You can see code of my arr structure and PriorityQueue collection. I normally add items to this collection like that:
arr.PriorityQueue.Add(new element((value(item, endPoint) + value(startPoint, item)),item));
I am curious that is other way to do this (add element(which is struct) object to List) ? In lambda way for example ? I just eager for knowledge :)

To add a new object to a list, you need to instantiate it.
The way you are doing it is correct, there is not lambda syntax or other syntactic sugar for this operation.

Another way is to use List.AddRange. It accepts an IEnumerable<T>, so you can pass it any collection of T, including arrays or the results of Linq expressions:
importantItems.AddRange(allItems.Where(item => item.IsImportant));

arrays arr = new arrays();
arr.PriorityQueue = new List<element>(
new [] {
new element {node = 1, priority =2 },
new element { node = 2, priority = 10}
//..
//..
});
arrays arr2 = new arrays();
arr2.PriorityQueue = new List<element>(
arr.PriorityQueue
);
arrays arr3 = new arrays();
arr3.PriorityQueue = new List<element>(arr2.PriorityQueue.FindAll(z => (1 == 1)));
arrays arr4 = new arrays();
arr4.PriorityQueue = new List<element>(arr3.PriorityQueue.ToArray());

Related

C# list of array type

I want to create a list of array type.
I want to create array containing values :
array = [a,b];
Then i want to put this array in list :
List<Array> list = new List<Array>( );
I am able to do this with list of string type but no luck with array type :
List<String> list = new List<String>( );
I am from javascript background, not much familiar with concept of collections in c#.
Also how can i create array in c# like we do in javascript :
var arrTemp = ["a", "b"];
Well, since your array is string[]:
var arrTemp = ["a", "b"];
you have to declare the required list as List<string[]>:
// list of string arrays
List<string[]> list = new List<string[]>() {
new string[] {"a", "b"}
};
In case you want to be able to put any array into the list declare it as loose as possible (List<object[]>):
// list of abitrary arrays
List<object[]> list = new List<object[]>() {
new string[] {"a", "b"},
new double[] {123.45, 789.12, 333.55},
new object[] {'a', "bcd", 1, 244.95, true},
};
Hope this can help you
var test = new List<int[]>();
You can actually create a list of arrays:
var listOfArrays = new List<Array>();
The problem with this is that it's difficult to use the arrays themselves, as the Array type doesn't support array syntax. (e.g. You can't do listOfArrays[0][0]) Instead, you have to use the GetValue method to do your retrieval:
var obj = listOfArrays[0].GetValue(0);
But this has another problem. The GetValue method returns object, so while you could always cast it to the desired type, you lose your type safety in choosing this approach.
Alternatively, you could just store object[] arrays:
var listOfArrays = new List<object[]>();
var obj = listOfArrays[0][0];
But while this solves the issue of the array notation, you still lose the type safety.
Instead, if at all possible, I would recommend finding a particular type, then just have arrays of that type:
var listOfArrays = new List<string[]>();
string s = listOfArrays[0][0];
for example, an array of strings would be
var arrayOfString = new string[]{"a","b"};
// or shorter form: string[] arrayOfString = {"a","b"};
// also: var arrayOfString = new[] { "a", "b" }
And then creating a list-of-arrayOfString would be
var listOfArrayOfString = new List<string[]>();
This works with any type, for example if you had a class MyClass
var arrayOfMyClass = new MyClass[]{ ... }; // ... is you creating instances of MyClass
var list = new List<MyClass[]>();

SortedList<> and its strange setters

I initially had some code, which when simplified, looks like this:
var planets = new List<Planet>
{
new Planet {Id = 1, Name = "Mercury"},
new Planet {Id = 2, Name = "Venus"},
};
I got into a scenario where the list was being populated all at once, but the reads weren't fast enough. And so, I changed this to use a SortedList instead.
I later realized that I could rewrite it like this
var planets = new SortedList<int, Planet>
{
{1, new Planet {Id = 1, Name = "Mercury"}},
{2, new Planet {Id = 2, Name = "Venus"}},
//in my actual code, i am reading the ids from a db
};
But before I got to this approach, I had the code written like this
var planets = new SortedList<int, Planet>
{
Keys = {1, 2},
Values =
{
new Planet {Id = 1, Name = "Mercury"},
new Planet {Id = 2, Name = "Venus"},
}
};
which gives me this exception
System.NotSupportedException: This operation is not supported on SortedList
nested types because they require modifying the original SortedList.
at System.ThrowHelper.ThrowNotSupportedException(ExceptionResource resource)
at System.Collections.Generic.SortedList`2.KeyList.Add(TKey key)
which I found to be very strange, coz IMHO, I wasn't really modifying the "original SortedList" as it claims, and what "nested types" is it talking about? Is it the list of keys internal to the SortedList?
I see then that the Keys and Values properties in SortedList don't actually have setters. They are read-only properties, and yet, I don't get a compile-time error. I am allowed to make a set call, as I can see in the stack trace with KeyList.Add. I feel the only reason why this fails is because of an explicit check within SortedList, which seems bizarre to me!
For instance
var str = new String {Length = 0}; gives me a compile-time error as expected, since Length is a read-only property, as does planets.Keys = null;
Someone please tell me - what simple fact am I overlooking here?
The code that you've written is comparable to this:
var planets = new SortedList<int, Planet>();
planets.Keys.Add(1);
planets.Keys.Add(2);
planets.Values.Add(new Planet { Id = 1, Name = "Mercury" });
planets.Values.Add(new Planet { Id = 2, Name = "Venus" });
SortedList requires that you add the value and key at the same time via SortedList<TKey, TValue>.Add(TKey key, TValue value) method, so that it can sort the value by the key. The implementation of the IList<T> which is used for Keys and Values internally does not support adding a respective key or value independently via the IList<T>.Add(T value) method.
You should be able to reproduce this error by calling Keys.Add(...) or Values.Add(...)
My initial query about the SortedList has now minimized to this concern about array, collection & object initializers, and the way the compiler interprets them differently. Thanks to #Haney again for the first answer to guide me towards this point of view, and to ILSpy for these insights.
Here are some array and collection initializers:
int[] a = { 1, 2, 3 };
int[] b = new int[] { 1, 2, 3 };
IList<int> c = { 1, 2, 3 };
IList<int> d = new int[] { 1, 2, 3 };
They all look kind of similar. Here, the compiler produces the exact same output for a & b. For c, we will get this compile-time error:
Can only use array initializer expressions to assign to array types.
Try using a new expression instead.
which makes sense since we shouldn't use array initializers for collections. But then, d produces the exact same result as a & b. And I thought that was an array initializer as well. Apparently not.
Now consider this class
class MyCollectionContainer
{
public int[] MyIntArray { get; set; }
public IList<int> MyList { get; set; }
}
and this code that operates on it
var containerA = new MyCollectionContainer { MyIntArray = { 1, 2, 3 } };
var containerB = new MyCollectionContainer { MyIntArray = new int[]{ 1, 2, 3 } };
var containerC = new MyCollectionContainer { MyList = { 1, 2, 3 } };
var containerD = new MyCollectionContainer { MyList = new int[]{ 1, 2, 3 } };
containerA gives this compile-time error:
Cannot initialize object of type 'int[]' with a collection initializer
For containerB, the compiler effectively converts it into this code:
MyCollectionContainer myCollectionContainer = new MyCollectionContainer();
myCollectionContainer.MyIntArray = new int[] {1, 2, 3};
For containerD, its pretty much the same, barring the fact that its another property that gets initialized:
MyCollectionContainer myCollectionContainer = new MyCollectionContainer();
myCollectionContainer.MyList = new int[] {1, 2, 3};
For containerC, the compiler morphs it into:
MyCollectionContainer myCollectionContainer = new MyCollectionContainer();
myCollectionContainer.MyList.Add(1);
myCollectionContainer.MyList.Add(2);
myCollectionContainer.MyList.Add(3);
This results in a run-time NullReferenceException since MyList is not initialized.
This means the only valid ways to initialize the collection container object here is containerB and containerD. To me, this clearly shows that object initializers are different when compared to array & collection initializers, in the way the compiler interprets them.

Concat not working - The underlying array is null

I am trying to Concat the two array IEnumerable lists and in result view it says The underlying array is null.
IEnumerable<ObjectToConcat> result = new ArraySegment<ObjectToConcat>();
var listA = new List<ObjectToConcat>();
var a = new ObjectToConcat
{OfficialId = Guid.NewGuid(), FirstName = "A Object"};
listA.Add(a);
var b = new ObjectToConcat
{OfficialId = Guid.NewGuid(), FirstName = "B Object"};
listA.Add(b);
// Error here is result view
result = result.Concat(listA);
var c = new ObjectToConcat
{OfficialId = Guid.NewGuid(), FirstName = "C Object"};
listB.Add(c);
// Error here is result view
result = result.Concat(listB);
Can anyone please suggest me what is wrong with my code. Or Concat does not work with List?
It would appear that this code:
IEnumerable<ObjectToConcat> result = new ArraySegment<ObjectToConcat>();
is an attempt to make an empty enumerable. You can do this more effectively and clearly by writing:
IEnumerable<ObjectToConcat> result = Enumerable.Empty<ObjectToConcat>();
That said, chaining a lot of Concat calls probably isn't the most effective, performance wise, if there are a lot of sub-lists. It's probably going to perform a bit better if you create a List<IEnumerable<ObjecToConcat>> allLists, add all of the sub-lists to that list, and then at the end you can write:
result = allLists.SelectMany(x => x);
to flatten it down to just a list of items.
you can have list of ObjectToConcat like below and add items to it using addrange method
List<ObjectToConcat> result = new List<ObjectToConcat>();
result.AddRange(listA);
Try this:
IEnumerable<ObjectToConcat> result =
new ArraySegment<ObjectToConcat>(new ObjectToConcat[0]).Array;

Clear array of strings

What is the easiest way to clear an array of strings?
Have you tried Array.Clear?
string[] foo = ...;
Array.Clear(foo, 0, foo.Length);
Note that this won't change the size of the array - nothing will do that. Instead, it will set each element to null.
If you need something which can actually change size, use a List<string> instead:
List<string> names = new List<string> { "Jon", "Holly", "Tom" };
names.Clear(); // After this, names will be genuinely empty (Count==0)
Array.Clear(theArray, 0, theArray.Length);
It depends on circumstance (like: what is in the array) but the best method usually is to create a new one. Dropping all references to the old one.
MyType[] array = ...
....
array = new MyType[size];
I think you can also get away with this for example:
SearchTerm = new string[]{};
You can try this.
result = result.Where(x => !string.IsNullOrEmpty(x)).ToArray();
string[] foo;
foo = string[""];
how about
string[] foo;
foo = null;

Sorting an array related to another array

I have two arrays, x and y, where y is the value of the tens of every element in x. Now, I want to sort y. But, the order of y will be different of x's. So, I can't tell after sorting which element in y was related to, for instance, x[0].
I want a "double sorting" maybe.
Array.Sort has an overload that accepts two arrays; one for the keys, and one for the items. The items of both are sorted according to the keys array:
int[] keys = { 1, 4, 3, 2, 5 };
string[] items = { "abc", "def", "ghi", "jkl", "mno" };
Array.Sort(keys, items);
foreach (int key in keys) {
Console.WriteLine(key); // 1, 2, 3, 4, 5
}
foreach (string item in items) {
Console.WriteLine(item); // abc, jkl, ghi, def, mno
}
So in your case, it sounds like you want:
Array.Sort(y,x); // or Sort(x,y); - it isn't 100% clear
How about?
var selectedArr = new int[] { 1, 3, 5, 7, 9 };
var unorderArr = new int[] { 9, 7, 5, 3, 1 };
var orderedArr = unorderArr.OrderBy(o => selectedArr.IndexOf(o));
If we have two arrays of complex objects and want to sort them according to one of the two arrays then we can use the next approach:
// We want to sort "people" array by "Name" and
// accordingly to it reorder "countries" array.
Person[] people = new Person[]
{
new Person {Name = "Fill"},
new Person {Name = "Will"},
new Person {Name = "Bill"},
};
Country[] countries = new Country[]
{
new Country {Name = "Canada"},
new Country {Name = "UK"},
new Country {Name = "USA"}
};
// Here we sort "people" array, but together with each "Person"
// in sorted array we store its "index" in unsorted array. Then we
// will use this "index" to reorder items in "countries" array.
var sorted = people
.Select((person, index) => new {person, index})
.OrderBy(x => x.person.Name)
.ToArray();
// Here "people" array is sorted by "Name", and
// "contries" array is reordered accordingly to it.
people = sorted.Select(x => x.person).ToArray();
countries = sorted.Select(x => countries[x.index]).ToArray();
Another approach is to use overload of the method Array.Sort with IComparer. At first we should implement IComparer:
private class PeopleComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
return x.Name.CompareTo(y.Name);
}
}
And then we can sort two our arrays:
Array.Sort(people, countries, new PeopleComparer());
Here is complete sample that demonstrates these two approaches.
If y is always the tens value of x, y probably shouldn't exist - you should probably just calculate it's value directly off of x when needed.
In general, sorting parallel arrays is only possible (without hand rolling a sort algorithm) when the sort algorithm takes a custom "swap" function, which you can implement in terms of swapping elements in both arrays simultaneously. std::sort in C++ and qsort in C don't allow this.
Also in the general case, consider a single array where the element is a pair of items, rather than a parallel array for each item. This makes using "standard" algorithms easier.

Categories