C# List<List<object[]>>() issue - Weird behavior - c#

I've been trying to do the following:
public List<List<object[]>> Queue = new List<List<object[]>>();
Queue = InitList(MaxLayerCapability, new List<object[]>());
Having
public List<T> InitList<T>(int count, T initValue)
{
return Enumerable.Repeat(initValue, count).ToList();
}
So here is where the issue resides:
Queue[2].Add(new object[] { "Draw", "Test" });
for ( int i = 0; i < MaxLayerCapability; i++)
{
Console.WriteLine(i + ">" + Queue[i].Count);
//Operate(Queue[i], i);
}
For some reason, I want that Queue[2] to contains elements, and all other lists (for example, Queue[0]) should have a count of 0.
It is at some point pushing all the elements into Queue, any ideas?
Here's what I'm getting:
0>1
1>1
2>1
3>1
4>1
5>1
Thanks in advance.

The problem is, as i understand it, that Repeat just repeats reference to the same instance of List.
I would refactor it this way:
public IEnumerable<T> InitList<T>(int count)
{
for (int i=0;i<count; i++)
{
yield return Activator.CreateInstance<T>();
}
}
I see correct results if i use fucntion this way:
Queue = InitList<List<object[]>>(3).ToList();

Related

Know if order is changed after calling List.Sort()?

For example, if a List contains {1,2,3,4,5}, calling Sort() will not change anything. But if a list contains {1,2,4,3,5}, then calling Sort() will change the order.
Is there any way to know if Sort() has changed anything? The method returns void.
P.S.
Actually, I tested this before posting this question. The idea was that x is an item currently before y, so if it needs to return a negative value, a swapping occurs. Unfortunately, it did not work... but why?
class IntComp : IComparer<int>
{
public int Compare(int x, int y)
{
var result = x - y;
if (result < 0)
_IsChanged = true;
return result;
}
private bool _IsChanged = false;
public bool IsChanged()
{
var result = _IsChanged;
_IsChanged = false;
return result;
}
}
var list = new List<int>() {};
Random r = new Random();
for (int i = 0; i < 1000; i++)
{
list.Add(r.Next());
}
var comparer = new IntComp();
Stopwatch w = new Stopwatch();
w.Start();
list.Sort(comparer);
w.Stop();
Debug.WriteLine(comparer.IsChanged() + ", " + w.Elapsed);
w.Restart();
list.Sort(comparer);
w.Stop();
Debug.WriteLine(comparer.IsChanged() + ", " + w.Elapsed);
Why not compare the original list with the sorted one?
var tmp = new List<MyType>(myList);
list.Sort();
if(tmp.SequenceEquals(list))
{
// both lists are equals so your list wasn´t modified by Sort
}
SequenceEquals will check if your two lists have the same elements in the exact same order.
EDIT: You could also write a simple method iterating your list and check if all elements are greater their ancestor. This should be the fasted way and avoids unnecessary iterations and copies of your list:
public bool IsOrdered<T>(this IEnumerable<T> src) where T: IComparable
{
for(int i = 1; i < myList.Count; i++)
{
if(myList[i - 1].CompareTo(myList[i]) == 1) return false;
}
return true;
}
If you want to keep only the original list in memory, what you can do is first check whether the list is sorted in the first place. If it is, no need for sorting and so it has not changed; if it is not sorted, you can sort it and then you know for sure it has changed.
With this, you don't have to create a clone of the list which is used to compare later, so this saves you some memory.

Why is it.current changing his values during debug?

I'm trying to get an element at a specific index with the method :
public T GetElem(int index)
{
var it = outerInstance.iterator();
var i = 0;
while (it.MoveNext() && i < index)
{
i++;
}
return it.Current;
}
I have created my own iterator which is an internal class of the outerInstance,during debug the current element is decreasing at the end it becomes null.
My test it's inside console app and looks like this :
Storage<int?> storage = new DynSLinkedList<int?>();
var ranked = new Ranked<int?>(storage);
if (ranked.IsEmpty())
{
Console.WriteLine("is empty \n");
}
for (var i = 1; i <= 10; i++)
ranked.Add(i);
if (!ranked.IsEmpty())
{
Console.WriteLine("is not empty \n");
}
if (ranked.Size() == 10)
{
Console.WriteLine("Size ok \n");
}
for (var i = 0; i <= 9; i++)
{
var element = ranked.GetElem(i);
if (element == 10 - i)
{
Console.WriteLine("get " + i + " elem ok \n");
}
}
Only for i=0 it gets right.
I have tried to write the equivalent for the java method:
#Override
public T getElem(int index) throws IndexOutOfBoundsException {
RWIterator<T> it=support.iterator();
int i=0;
while (it.hasNext() && i<index){
it.next();
i++;
}
return it.next();
}
Your problem is that you are using a single instance to iterate over in the Ranked.GetElem method. The first time you call ranked.GetElem, passing 0, the iterator will be moved one step (it.MoveNext).
At this point the iterator is already pointing to the second element in your list. The next time you call ranked.GetElem, passing 1, the iterator will be moved two spaced further, ending up returning the third element as opposed to the one you are expecting (the second). So on and so forth.
You need to either change the overall approach you are taking or reset the iterator inside the GetElem method so it always starts from the first element.
Try this (assuming you are implementing the Reset() method correctly):
public T GetElem(int index)
{
var it = outerInstance.iterator();
it.Reset();
var i = 0;
while (it.MoveNext() && i < index)
{
i++;
}
return it.Current;
}

Is there another way to take N at a time than a for loop?

Is there a more elegant way to implement going 5 items at a time than a for loop like this?
var q = Campaign_stats.OrderByDescending(c=>c.Leads).Select(c=>c.PID).Take(23);
var count = q.Count();
for (int i = 0; i < (count/5)+1; i++)
{
q.Skip(i*5).Take(5).Dump();
}
for(int i = 0; i <= count; i+=5)
{
}
So you want to efficiently call Dump() on every 5 items in q.
The solution you have now will re-iterate the IEnumerable<T> every time through the for loop. It may be more efficient to do something like this: (I don't know what your type is so I'm using T)
const int N = 5;
T[] ar = new T[N]; // Temporary array of N items.
int i=0;
foreach(var item in q) { // Just one iterator.
ar[i++] = item; // Store a reference to this item.
if (i == N) { // When we have N items,
ar.Dump(); // dump them,
i = 0; // and reset the array index.
}
}
// Dump the remaining items
if (i > 0) {
ar.Take(i).Dump();
}
This only uses one iterator. Considering your variable is named q, I'm assuming that is short for "query", which implies this is against a database. So using just one iterator may be very beneficial.
I may keep this code, and wrap it up in an extension method. How about "clump"?
public static IEnumerable<IEnumerable<T>> Clump<T>(this IEnumerable<T> items, int clumpSize) {
T[] ar = new T[clumpSize];
int i=0;
foreach(var item in items) {
ar[i++] = item;
if (i == clumpSize) {
yield return ar;
i = 0;
}
}
if (i > 0)
yield return ar.Take(i);
}
Calling it in the context of your code:
foreach (var clump in q.Clump(5)) {
clump.Dump();
}
try iterating by 5 instead!
for(int i = 0; i < count; i += 5)
{
//etc
}
Adding more LINQ with GroupBy and Zip:
q
// add indexes
.Zip(Enumerable.Range(0, Int32.MaxValue),(a,index)=> new {Index=index, Value=a})
.GroupBy(m=>m.Index /5) // divide in groups by 5 items each
.Select(k => {
k.Select(v => v.Value).Dump(); // Perform operation on 5 elements
return k.Key; // return something to satisfy Select.
});

Problem with delegates in C#

In the following program, DummyMethod always print 5. But if we use the commented code instead, we get different values (i.e. 1, 2, 3, 4). Can anybody please explain why this is happenning?
delegate int Methodx(object obj);
static int DummyMethod(int i)
{
Console.WriteLine("In DummyMethod method i = " + i);
return i + 10;
}
static void Main(string[] args)
{
List<Methodx> methods = new List<Methodx>();
for (int i = 0; i < 5; ++i)
{
methods.Add(delegate(object obj) { return DummyMethod(i); });
}
//methods.Add(delegate(object obj) { return DummyMethod(1); });
//methods.Add(delegate(object obj) { return DummyMethod(2); });
//methods.Add(delegate(object obj) { return DummyMethod(3); });
//methods.Add(delegate(object obj) { return DummyMethod(4); });
foreach (var method in methods)
{
int c = method(null);
Console.WriteLine("In main method c = " + c);
}
}
Also if the following code is used, I get the desired result.
for (int i = 0; i < 5; ++i)
{
int j = i;
methods.Add(delegate(object obj) { return DummyMethod(j); });
}
The problem is that you're capturing the same variable i in every delegate - which by the end of the loop just has the value 5.
Instead, you want each delegate to capture a different variable, which means declaring a new variable in the loop:
for (int i = 0; i < 5; ++i)
{
int localCopy = i;
methods.Add(delegate(object obj) { return DummyMethod(localCopy); });
}
This is a pretty common "gotcha" - you can read a bit more about captured variables and closures in my closures article.
This article will probably help you understand what is happening (i.e. what a closure is): http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx
If you look at the code generated (using Reflector) you can see the difference:
private static void Method2()
{
List<Methodx> list = new List<Methodx>();
Methodx item = null;
<>c__DisplayClassa classa = new <>c__DisplayClassa();
classa.i = 0;
while (classa.i < 5)
{
if (item == null)
{
item = new Methodx(classa.<Method2>b__8);
}
list.Add(item);
classa.i++;
}
foreach (Methodx methodx2 in list)
{
Console.WriteLine("In main method c = " + methodx2(null));
}
}
When you use the initial code it creates a temporary class in the background, this class holds a reference to the "i" variable, so as per Jon's answer, you only see the final value of this.
private sealed class <>c__DisplayClassa
{
// Fields
public int i;
// Methods
public <>c__DisplayClassa();
public int <Method2>b__8(object obj);
}
I really recommend looking at the code in Reflector to see what's going on, its how I made sense of captured variables. Make sure you set the Optimization of the code to ".NET 1.0" in the Option menu, otherwise it'll hide all the behind scenes stuff.
I think it is because the variable i is put to the heap (it's a captured variable)
Take a look at this answer.

Why is my IEnumerable<String> using yield return slower to iterate then List<String>

I have been testing out the yield return statement with some of the code I have been writing. I have two methods:
public static IEnumerable<String> MyYieldCollection {
get
{
wrapper.RunCommand("Fetch First From Water_Mains");
for (int row = 0; row < tabinfo.GetNumberOfRows() ; row++) //GetNumberOfRows
//will return 1000+ most of the time.
{
yield return wrapper.Evaluate("Water_Mains.col1");
wrapper.RunCommand("Fetch Next From Water_Mains");
}
}
}
and
public static List<String> MyListCollection
{
get
{
List<String> innerlist = new List<String>();
wrapper.RunCommand("Fetch First From Water_Mains");
for (int row = 0; row < tabinfo.GetNumberOfRows(); row++)
{
innerlist.Add(wrapper.Evaluate("Water_Mains.col1"));
wrapper.RunCommand("Fetch Next From Water_Mains");
}
return innerlist;
}
}
then I use a foreach loop over each collection:
foreach (var item in MyYieldCollection) //Same thing for MyListCollection.
{
Console.WriteLine(item);
}
The funny thing is for some reason I seem to be able to loop over and print out the full MyListCollection faster then the MyYieldCollection.
Results:
MyYieldCollection -> 2062
MyListCollection -> 1847
I can't really see a reason for this, am I missing something or is this normal?
How have you done your timings? Are you in the debugger? In debug mode? It looks like you are using DataTable, so I used your code as the template for a test rig (creating 1000 rows each time), and used the harness as below, in release mode at the command line; the results were as follows (the number in brackets is a check to see they both did the same work):
Yield: 2000 (5000000)
List: 2100 (5000000)
Test harness:
static void Main()
{
GC.Collect(GC.MaxGeneration,GCCollectionMode.Forced);
int count1 = 0;
var watch1 = Stopwatch.StartNew();
for(int i = 0 ; i < 5000 ; i++) {
foreach (var row in MyYieldCollection)
{
count1++;
}
}
watch1.Stop();
GC.Collect(GC.MaxGeneration,GCCollectionMode.Forced);
int count2 = 0;
var watch2 = Stopwatch.StartNew();
for (int i = 0; i < 5000; i++)
{
foreach (var row in MyListCollection)
{
count2++;
}
}
watch1.Stop();
Console.WriteLine("Yield: {0} ({1})", watch1.ElapsedMilliseconds, count1);
Console.WriteLine("List: {0} ({1})", watch2.ElapsedMilliseconds, count2);
}
(note you shouldn't normally use GC.Collect, but it has uses for levelling the field for performance tests)
The only other change I made was to the for loop, to avoid repetition:
int rows = tabinfo.Rows.Count;
for (int row = 0; row < rows; row++) {...}
So I don't reproduce your numbers...
What happens if one iteration of your loop is expensive and you only need to iterate over a few items in your collection?
With yield you only need to pay for what you get ;)
public IEnumerable<int> YieldInts()
{
for (int i = 0; i < 1000; i++)
{
Thread.Sleep(1000) // or do some other work
yield return i;
}
}
public void Main()
{
foreach(int i in YieldInts())
{
Console.WriteLine(i);
if(i == 42)
{
break;
}
}
}
My guess is that the JIT can better optimize the for loop in the version that returns the list. In the version that returns IEnumerable, the row variable used in the for loop is now actually a member of a generated class instead of a variable that is local only to the method.
The speed difference is only around 10%, so unless this is performance critical code I wouldn't worry about it.
As far as I understand it, "yield return" will keep looping until it runs our of stuff to do and the function/property exits, returning a filled IEnumarable. In other words instead of the function being called for each item in the foreach loop, it is called once and before anything inside the foreach loop is executed.
It could be by the type of collections that are returned. Perhaps the List can be iterated over faster than whatever datastructure the IEnumerable is.

Categories

Resources