Adding data to an array of struct - c#

I'm trying to add/remove data from an array of a defined struct.
struct process
{
public int Proc_Id;
public int Proc_BurstTime;
public int Proc_Priority;
public override string ToString()
{
return "ID: " + Proc_Id.ToString() + " Time: " + Proc_BurstTime.ToString() + " Prior: " + Proc_Priority.ToString();
}
};
readonly process[] ProcessList = new process[]
{
new process{ Proc_Id = 1, Proc_BurstTime = 3000, Proc_Priority = 1},
new process{ Proc_Id = 2, Proc_BurstTime = 5000, Proc_Priority = 2},
new process{ Proc_Id = 3, Proc_BurstTime = 1000, Proc_Priority = 3},
new process{ Proc_Id = 4, Proc_BurstTime = 10000, Proc_Priority = 4}
};
I see it is readonly (based on some Google searches, I have no other option.
I can modify the data, but how do I go about adding data to the ProcessList? I've tried ProcessList.Add(~), but that's not working.
Basically, what I'm exactly trying to do is populate this array of structs into a ListBox control. I have been able to initially populate it by using DataSource, I've also been able to modify the contents and "re-datasource" it to update the ListBox. However, I cannot ADD or REMOVE processes. Does anyone know what I can do?

You'll need to use a collection.
A List<T> would do just fine.
var processes = new List<process>();
processes.Add(new process
{
Proc_Id = 1,
Proc_BurstTime = 3000,
Proc_Priority = 1
});
Modifying your code a bit would result in this below.
List<process> ProcessList = new List<process>()
{
new process {Proc_Id = 1, Proc_BurstTime = 3000, Proc_Priority = 1},
new process {Proc_Id = 2, Proc_BurstTime = 5000, Proc_Priority = 2},
new process {Proc_Id = 3, Proc_BurstTime = 1000, Proc_Priority = 3},
new process {Proc_Id = 4, Proc_BurstTime = 10000, Proc_Priority = 4}
};
This collection type also has the Add method you are referring to in your question.

Using readonly prevents the variable, ProcessList from being assigned a new list. If you removed readonly you could create a new array with the new, desired size and copy the elements from the old array to it, then assign it to ProcessList. This is unlikely what you really want to do. The better solution would be, instead, to use a collection that allows you to add/remove elements. An array, once created, cannot have it's size changed. A List<T> (or some other generic collection), is built to allow new elements to be added or existing elements to be removed, with the size adjusting to reflect the number of current elements.
readonly List<process> ProcessList = new List<process>
{
new process { Proc_Id = 1, Proc_BurstTime = 3000, Proc_Priority = 1 },
new process { Proc_Id = 2, Proc_BurstTime = 5000, Proc_Priority = 2 },
new process { Proc_Id = 3, Proc_BurstTime = 1000, Proc_Priority = 3 },
new process { Proc_Id = 4, Proc_BurstTime = 10000, Proc_Priority = 4 }
};

Related

Select different objects from two collections

I have the following class:
struct UserRecord
{
//--- common settings
int login; // login
int leverage; // leverage
int enable; // enable
}
And I have two lists:
List<UserRecord> base_data = new List<UserRecord>();
base_data.Add(new UserRecord(){login = 1, leverage = 1000, enable = 0});
base_data.Add(new UserRecord(){login = 2, leverage = 100, enable = 0});
base_data.Add(new UserRecord(){login = 3, leverage = 10, enable = 1});
base_data.Add(new UserRecord(){login = 4, leverage = 10000, enable = 0});
List<UserRecord> snapshot_data= new List<UserRecord>();
snapshot_data.Add(new UserRecord(){login = 1, leverage = 1000, enable = 1});
snapshot_data.Add(new UserRecord(){login = 2, leverage = 100, enable = 0});
snapshot_data.Add(new UserRecord(){login = 3, leverage = 10, enable = 1});
snapshot_data.Add(new UserRecord(){login = 4, leverage = 10000, enable = 1});
My goal is to filter the records, and get the two records in a new list, that are with different fields, in this case only the field 'enable' is different.
var filtered_data = new List<UserRecord>(); // here records with login 1 and 4 should go.
Do you have any suggestions?
You may look for Enumerable.Except() from System.Linq to find the differences between both enumerable.
using System.Linq;
List<UserRecord> filter_data = base_data.Except(snapshot_data)
.ToList();
Demo # .NET Fiddle
Another approach is if you just want to compare the difference in enable based on the items with the same login and leverage from the different lists.
You need to join both lists by the key(s) and query the record from the first list with the different enable value.
List<UserRecord> filter_data = (from a in base_data
join b in snapshot_data on new { a.login, a.leverage } equals new { b.login, b.leverage }
where a.enable != b.enable
select a
).ToList();
Demo Solution 2 # .NET Fiddle

C# merge multiple lists by id and summing the property

I got a grapic class which looks like this:
public class Graphic
{
public int id { get; set; }
public int Counter { get; set; }
}
and now i have 3 lists of grapic:
public void myFunction()
{
List<Graphic> l1= new List<Graphic> ();
List<Graphic> l2= new List<Graphic> ();
List<Graphic> l3= new List<Graphic> ();
l1.Add(new Graphic {id = 1, Counter = 4});
l1.Add(new Graphic {id = 2, Counter = 2});
l1.Add(new Graphic {id = 3, Counter = 9});
l1.Add(new Graphic {id = 4, Counter = 1});
l2.Add(new Graphic {id = 1, Counter = 1});
l2.Add(new Graphic {id = 2, Counter = 2});
l2.Add(new Graphic {id = 3, Counter = 3});
l2.Add(new Graphic {id = 5, Counter = 1});
l3.Add(new Graphic {id = 1, Counter = 12});
l3.Add(new Graphic {id = 7, Counter = 1});
l3.Add(new Graphic {id = 8, Counter = 3});
l3.Add(new Graphic {id = 4, Counter = 1});
}
And i need a code which will merge these 3 lists, each graphic with it's ID and the counter property will be summed up, so the result will be:
var mergedList = {
Graphic {id = 1, Counter = 17},
Graphic {id = 2, Counter = 4},
Graphic {id = 3, Counter = 12},
Graphic {id = 4, Counter = 2},
Graphic {id = 5, Counter = 1},
Graphic {id = 7, Counter = 1},
Graphic {id = 8, Counter = 3}
}
any idea will help me.
Is there a way to do that efficiently with LINQ?
Use .Concat to merge the 3 lists and then GroupBy to get all the Counter values of the different ids:
var result = l1.Concat(l2)
.Concat(l3)
.GroupBy(item => new { item.id, item.Geometry }, item => item.Counter)
.Select(group => new Graphic
{
id = group.Key,
Counter = group.Sum()
}).ToList();
See collection initializer for a neater way to initialize the lists:
List<Graphic> l1 = new List<Graphic>
{
new Graphic { id = 2, Counter = 2 },
new Graphic { id = 3, Counter = 9 },
new Graphic { id = 4, Counter = 1 },
new Graphic { id = 1, Counter = 4 },
};
I also suggest reading C# naming conventions for the naming of your function and the properties.

How can I repopulate an array?

I have code that populates an array:
var counters = new[] { 1,2,4,8 }
This works good but later on in my code I would like to do something like this:
counters = new[] { 2,2,3,5 }
Is there some way I can do this? I am very new to C# and still learning
The code you wrote in your question would work fine: the first line will create a new array, the second line will also create a new array and will assign the new array to the existing variable. The old integer array will be replaced (and later be garbage collected)
What is your problem? Your code is valid:
var counters = new[] { 1,2,4,8 };
counters = new[] { 2, 2, 3, 5 };
Your code will work, but it does not repopulate the array, it creates a new array.
You could do this
Array.Copy( new int[] { 2,2,3,5 }, counters, 4);
Yes, you can do as you have written.
However, note that this will create a new array, not replace the values in the old array. That makes a difference if another variable holds a reference to the same array.
Example 1
var counters = new[] { 1, 2, 4, 8 };
var counters2 = counters;
counters = new[] { 2, 2, 3, 5 };
Console.WriteLine(counters2[0].ToString()); // outputs 1
Example 2
var counters = new[] { 1, 2, 4, 8 };
var counters2 = counters;
counters[0] = 2;
counters[1] = 2;
counters[2] = 3;
counters[3] = 5; // or use Array.Copy as suggested by Henrik
Console.WriteLine(counters2[0].ToString()); // outputs 2

Sorting nested Lists within object using c# Lambda Expressions

I have an object
TestCollection testCollection = new TestCollection()
{
new Test
{
quickTest =
new QuickTest
{
id = a,
sortField = 3,
nestedQuickTest =
new List<NestedQuickTest>
{
new NestedQuickTest{sortField = 1},
new NestedQuickTest{sortField = 2},
new NestedQuickTest{sortField = 3},
new NestedQuickTest{sortField = 4},
}
}
},
new Test
{
quickTest =
new QuickTest
{
id = b,
sortField = 2,
nestedQuickTest =
new List<NestedQuickTest>
{
new NestedQuickTest{sortField = 21},
new NestedQuickTest{sortField = 32},
new NestedQuickTest{sortField = 11},
new NestedQuickTest{sortField = 2},
}
}
},
new Test
{
quickTest =
new QuickTest
{
id = c,
sortField = 1,
nestedQuickTest =
new List<NestedQuickTest>
{
new NestedQuickTest{sortField = 3},
new NestedQuickTest{sortField = 2},
new NestedQuickTest{sortField = 8},
new NestedQuickTest{sortField = 1},
}
}
},
};
1) I would like to sort this object using lambda expressions.
2) I would like to get back the object sorted by the first in Asc order and then by the in Asc order.
3) I would like to remove the last property in both nested List<> objects so there are only two objects in each.
I apologize if this is a little confusing but I would like to do something like this:
var sorted = testCollection.OrderBy(x => x.quickTest.sortField).ThenBy(y => y.quickTest.nestedQuickTest.Select(z => z.sortField)).Take(2);
The end result would be:
TestCollection testCollection = new TestCollection()
{
,
new Test
{
quickTest =
new QuickTest
{
id = c,
sortField = 1,
nestedQuickTest =
new List<NestedQuickTest>
{
new NestedQuickTest{sortField = 1},
new NestedQuickTest{sortField = 2}
}
}
},
new Test
{
quickTest =
new QuickTest
{
id = b,
sortField = 2,
nestedQuickTest =
new List<NestedQuickTest>
{
new NestedQuickTest{sortField = 2},
new NestedQuickTest{sortField = 11}
}
}
}
};
Thanks in advance for your help, I can't seem to get my desired results and I know I am missing something obvious.
If I understand what you are saying you want to order the objects in MyOrderList by the property with the NestedObject, which is a collection of objects who should themselves ordered by the value of the AnotherNestedObject, which is also a list.
Well first of all you need to implement a Icomparer or something like that to set the rules of what makes one list bigger than the other.
See, you want to order objects in a list by a value, if its an int, well thats easy, but being a list, what are the rules to determine which one is bigger? Is it the one with more elements? The one with biggest sum of elements?
You need to figure out this first
EDIT:
Okay I think I understand your question better, you just want to order the outer lists objects by the int, and then also have the list inside each of those elements ordered too.
I think it would be easier if you did this in 2 steps something like:
var orderedTestCollection = testCollection.Orderby(tc=>tc.quickTest.SortField) // orders all the testCollection objects
//orders and only takes 2 elements of the lists inside the each test collection object
foreach(var tc in testCollection)
{
tc.quickTest.NestedQuickTest = tc.quickTest.NestedQuickTest.Orderby(nqt=>nqt.SortField).Take(2);
}

Easiest way to create a nested list from flat data

Assume I have the following information in a flat format, for example a list of objects:
List<Line> lines = new List<Line>
{
new Line{Id = 1, Level = 0},
new Line{Id = 2, Level = 1},
new Line{Id = 3, Level = 1},
new Line{Id = 4, Level = 2},
new Line{Id = 5, Level = 2},
new Line{Id = 6, Level = 1},
new Line{Id = 7, Level = 1},
new Line{Id = 8, Level = 2},
new Line{Id = 9, Level = 1}
};
Each object has an id and a level. What I want to end up with a nested list. For this I have a class which can have a list of children, based on the level.
public class NestedLine
{
public int Id;
public List<NestedLine> Children = new List<NestedLine>();
}
What's the easiest way to convert that flat list into a nested list?
EDIT: The only information on how to construct the list is the order of the lines and the level. This should be the result:
1
--2
--3
--4
--5
--6
--7
--8
--9
Here is my attempt.
Calling code
List<Line> lines = new List<Line>
{
new Line{Id = 1, Level = 0},
new Line{Id = 2, Level = 1},
new Line{Id = 3, Level = 1},
new Line{Id = 4, Level = 2},
new Line{Id = 5, Level = 2},
new Line{Id = 6, Level = 1},
new Line{Id = 7, Level = 1},
new Line{Id = 8, Level = 2},
new Line{Id = 9, Level = 1}
};
NestedLine nestedLine = Recusrsive(lines, 0);
Recursive Method
private NestedLine Recusrsive(List<Line> lines, int listPos)
{
NestedLine retVal = new NestedLine();
Line line = lines[listPos];
retVal.Id = line.Id;
for (int iItem = listPos + 1; iItem < lines.Count; iItem++)
if (lines[iItem].Level == line.Level + 1)
retVal.Children.Add(Recusrsive(lines, iItem));
else if (lines[iItem].Level <= line.Level) return retVal;
return retVal;
}
Can you provide a little more information here? This looks to me like you are really dealing with a tree structure:
1
-> 2
-> 3
-> -> 4
-> -> 5
-> 6
-> 7
-> -> 8
-> 9
am i correct? and if so, what is the rule for determining the parent of the lower level nodes?
The first thing that comes to mind is to use a recursive constructor for your NestedLine class:
public NestedLine(List lines)
Use a stack to keep track what was the last item added at each level, pushing and popping as you go along:
var stack = new Stack<NestedLine>();
foreach (var line : lines) {
while (stack.Count > line.Level) {
// Pop items until the top element is one up from current level
stack.Pop()
}
var child = new NestedLine{Id = line.Id};
if (stack.Count > 0) {
// if there is a parent, add the child to its children
stack.Peek().Children.Add(child);
}
// add current line as the deepest item
stack.Push(child);
}
NestedLine root;
while (stack.Count) {
root = stack.Pop();
}
Disclaimer: I haven't actually done much C# programming so this might contain some trivial errors.

Categories