I am new to GTK and I am learning to use a TreeStore. I am using C#.
I would like to count the parent items in a TreeStore so that when I append an item I can concatenate the title with an appropriate number. (e.g. "Product 0", "Product 1" etc.
I have found a way to do what I want by iterating through the entire tree and counting the items. Like this:
trs_inspectionStore.GetIterFirst (out iter); // Go to first item in store.
int n = 0;
while (trs_inspectionStore.IterIsValid (iter)) // Loop while the iter is valid
{
n++;
trs_inspectionStore.IterNext (ref iter); // Next item!
}
Console.WriteLine (n);
I am wondering if there is a better way. I was hoping to find some Count property or something along those lines. Any ideas? Or am I already using the best method?
I found the answer to this problem myself:
To count the number of top-level rows in a TreeStore, use the NChildren() method of a model. This method is generally used to count the number of children of a row, and you pass it an 'Iter' object as a parameter. But if, instead, you call it with no Iter (zero parameters) it returns a count of the number of top level rows:
int count = Model.IterNChildren();
Related
I have been researching this topic and got conflicting answers. Any help is appreciated.
For an assignment, I am instructed to create a structure of arrays. I am trying to delete an entry in one case, and change in another. This is supposed to be by one of the fields and not by index number.
var countOfEmployees = 0;
var employees = new EmployeeData[100];
Console.Write("Please enter employee you want to delete:");
string deleteEmployee = Console.ReadLine();
bool deleted = false;
for (int x = 0; x < countOfemployees; x++)
{
if (items[x].ItemNumber == deleteItemNumber)
{
deleted = true;
}
if (true)
{
//code goes here
}
Any help is appreciated!
In an array, you might be able to delete the value from the place holder, but you will not be able to remove the actual item without some footwork.
Basically, what you can do is: Find the value you've searched for, and replace it with a null and treat it orrespondingly in every other function.
Option 2 would be to remove the item and then use a function that would "shift" all the values with a higher index upwards.
Option 3 is to use the advanced functions C#/.NET has to offer with collections, create a List, remove the item and cast back to an array.
var employees = new EmployeeData[100];
var list = employees.ToList();
int index=-1;
//search through in a loop (won't write it here)...
index = x; //get the index in your list then break the loop
break; //end the loop
list.RemoveAt(index); //delete the spot outside the loop
employees=list.ToArray();
Of course there's checks needed if the search didn't find anything, but i think you can manage to implement that without my help.
And this is of course me assuming that there's only ONE entry with that kind of value in the array.
If it's not, you're gonna have to loop through and erase them until the search doesn't find anything anymore.
I'm trying to make a program that reads a file with 50 random words, it stores the words with 3 letters or less in a list called SmallWords and the words with 4 letters or more in a list called LargeWords. I'm using Windows Forms and I have a ListView control with 2 columns... 'Small Words' and 'Large Words'. It seems obvious that what I want to do is just put the words in its corresponding column. The thing is that the file doesn't have like 25 small and 25 large words, you know? Maybe it has 30 small words and 20 large words, so when I do this loop to add items to the ListView, it throws this exception:
ArgumentOutOfRangeException.
This is my code
var MaxNum = Math.Max(SmallWords.Count, LargeWords.Count);
for (var index = 0; index < MaxNum; index++)
{
ListViewItem item = new ListViewItem(SmallWords[index]);
item.SubItems.Add(LargeWords[index]);
listView1.Items.Add(item);
}
The exception is thrown at this line item.SubItems.Add(LargeWords[index]);
Is there a way to handle this? Or like another way to add the items to the columns? I know it works because if change Math.Max(...); to Math.Min(...) it adds the words but just the 20 large words and 20 small words, I'm going to be missing 10 small words in the SmallWords column.
Thanks
You have two arrays with different lengths and try to loop through and access up the the max of both arrays. That's never going to work. Once you hit the limit of the smaller array, you'll get the out of range exception.
Two options to fix depend on what you want to do. You can loop through to the max of the smaller array, or you can skip the part that deals with the smaller array once you hit its max.
var MaxNum = Math.Min(SmallWords.Count, LargeWords.Count);
// ^--- Changed Max to Min
for (var index = 0; index < MaxNum; index++)
{
ListViewItem item = new ListViewItem(SmallWords[index]);
item.SubItems.Add(LargeWords[index]);
listView1.Items.Add(item);
}
I think you should look at this problem in a different way. Basically you are adding a large word at i index to a small word at the same index. Which means that you have to have a SmallWord to add a LargeWord as a subitem. Forget finding the min or max, just loop through the count of SmallWords and only add the LargeWords if the index is in range:
for (var index = 0; index < SmallWords.Length; index++)
{
ListViewItem item = new ListViewItem(SmallWords[index]);
if(index < LargeWords.Length)
{
item.SubItems.Add(LargeWords[index]);
}
listView1.Items.Add(item);
}
I have tried to get the point across in the title as best as I can but basically what I want to do is add certain items to List while running a loop so I don't have to manually put them into an if statement. Let me please show an example so that I can explain properly.
Example :-
What I need is :- the first number would be 500 and that would be in index 0, then i want a loop to add 150 to the last number generated so that the int list would look like this,
index 0 = 500
index 1 = 650
index 2 = 800
index 3 = 950
Do this repeatedly until say the last number will read 2,000,000
Now I believe that this would be simple to run a loop and base it on conditions but I can only seem to figure out to run a loop that will increment the value in 1.
Hope I have explained well enough
Regards,
M
Now I believe that this would be simple to run a loop and base it on
conditions but I can only seem to figure out to run a loop that will
increment the value in 1.
This is not true, you can adjust the increment of the iterator as you wish.
var numbers = new List<int>();
for(int i=500; i<=2000000; i+=150)
{
numbers.Add(i);
}
For further information on this, please have a look here.
Just another implementation:
var result = new List<int>();
var number = 500;
do
{
result.Add(number);
number+= 150;
} while (number <= 2000000);
Let me explain the situation first:
I receive a value from my Binary Search on a collection, and quickly jump to that to do some coding. Next I want to jump to the next item in the list. But this next item is not exactly the one that follows it could be 3 or 4 items later. Here is my data to understand the sitatuion
Time ID
0604 ABCDE
0604 EFGH
0604 IJKL
0626 Some Data1
0626 Some Data2
0626 Some Data3
0626 Some Data4
Let's say Binary search return's index 0, I jump to index 0 (0604 ABCDE). I process/consume all 0604. Now I am at index 0, how do I jump to index 3 (0626) and consume / process all of it. Keeping in mind this will not always be the same. Data can be different. So I can't simply jump : index + 3
Here's my code:
var matches = recordList.Where(d => d.DateDetails == oldPointer);
var lookup = matches.ToLookup(d => d.DateDetails).First();
tempList = lookup.ToList();// build templist
oldPointer here is the index I get from Binary search. I take this up and build a templist. Now after this I want to jump to 0626.
How many records with the same "old pointer" do you typically expect? Is usually going to be less than 100? if so: don't over-complicate it - just iterate:
public static int FindNextPointerIndex(int oldIndex, string oldPointer, ...)
{
for(int i = oldIndex + 1; i < collection.Count ; i++)
{
if(collection[i].DateDetails != oldPointer) return i;
}
return -1;
}
If you want something more elegant, you will have to pre-index the data by DateDetails, presumably using something like a ToLookup over the entire collection, but: note that this makes changes to the data more complicated.
Have a look at Skip List , http://en.wikipedia.org/wiki/Skip_list
It will allow you to jump forward more than 1 in your linked list, but the down side to find the start of your search will be O(n)
The requirement I have is for every type T, I have a number of elements (between 1-30+) and at first I need random item, then I need the next, and when I reach the last item, it should return the first one and so on.
So say T is Icon, and the collection is Images (instance).
I want to have:
// program start:
Icon icon = RandomIcon(); // say 5th one for this case
// user clicks next icon:
icon = current++; (6, 7, 8, 1, 2, ...)
To me a circular linked list makes sense, except that I have to do O(n) where n is the random index.
I want to have the cleanest, best implemenation, hence the question.
Another possible solution is to create a linked list with the underlying data structure being an array. This way you can index in at O(1) while maintaining your "circularity"
public class myLL
{
private T[] items;
private int i;
private int max_size;
public T GetCurrent() {
return items[i];
}
public T GetNext() {
i = i++ % max_size;
return items[i];
}
}
I would consider using a custom class containing an array or a List<T> internally, and making a custom enumerator that starts at any index, and enumerates around the loop.
The main reason I think this would be better than a LinkedList has to do with this line:
Icon icon = RandomIcon(); // say 5th one for this case
It is much easier and more performant to get a random item from an indexible collection than a linked list.... And with 30 elements, enumerating will be quick in either case.
To handle the iteration in a circle, all you need is something like this:
class CircularlyEnumerableList<T>
{
private List<T> list;
// Implement whatever you need for list...
IEnumerable<T> EnumerateFromElement(int index)
{
for (int i=index; i<list.Count; ++i)
yield return list[i];
for (int i=0; i<index; ++i)
yield return list[i];
}
}
Circular list is good
Since you have around 30 elements (and not like 3000, say), you could consider an indexed table rather than a linked list
This will work straight away if your elements do not keep getting added and removed
If you have dynamically inserted and deleted elements, you could still write some code to handle that (coz, small list)
If all this works for you, all that remains is a random between 1-N.
If your item count per list is small, it would be an over kill to implement a lined list
However, if you choose to do so, you could still afford a first traversal down the list to the randomly picked start point
Why use a linked list at all? Use an array and store the index of the current item. When a function is called to get the next item, increment the index. If the index is greater than the number of elements, set the index to zero.