C# Sorted list without LINQ and SORT - c#

My question is that is it possible to create a list that sorts the objects in it upon these object being placed in them?
After not getting anywhere, I made a new linked list. The only task is to make this list ordered by the string field of the objects it will containt while remaining foreachable.
I have the following code:
class LancoltLista<T> : IEnumerable
{
class ListaElem
{
public T tartalom;
public ListaElem kovetkezo;
}
ListaElem fej;
public void ElejereBeszuras(T elem)
{
ListaElem uj = new ListaElem();
uj.tartalom = elem;
uj.kovetkezo = fej;
fej = uj;
}
public void VegereBeszuras(T elem)
{
if (fej == null)
{
ElejereBeszuras(elem);
}
else
{
ListaElem e = fej;
while (e.kovetkezo != null)
{
e = e.kovetkezo;
}
ListaElem uj = new ListaElem();
uj.tartalom = elem;
e.kovetkezo = uj;
}
}
public IEnumerator GetEnumerator()
{
return new ListaBejaro(fej);
}
class ListaBejaro : IEnumerator<T>
{
ListaElem elso, jelenlegi;
public ListaBejaro(ListaElem elso)
{
this.elso = elso;
jelenlegi = null;
}
public bool MoveNext()
{
if (jelenlegi == null)
{
jelenlegi = elso;
}
else
{
jelenlegi = jelenlegi.kovetkezo;
}
return jelenlegi != null;
}
public void Reset()
{
jelenlegi = null;
}
object IEnumerator.Current
{
get { return this.jelenlegi.tartalom; }
}
public T Current
{
get { return this.jelenlegi.tartalom; }
}
public void Dispose()
{
elso = null;
jelenlegi = null;
}
}
}
The problem here is that I'm not able to compare p.kulcs and kulcs.

For real world applications you could use the built-in SortedList<T>.
For your homework, you will have to check every item that you get in your add method against the entire list and insert it into the correct place: between the last element that it's grater than or equal to, and the first element that it's smaller then.
Of course, if the list is empty, or if there is no element greater than the one you add, then you simply append the element to the last available location.
Since this is homework, I'll leave you to write the code yourself.

Related

How to get Next and Previous values of Enumerator List?

When am trying to while loop of Enumerator List, How to get Next and previous values. Please find the below code.
public static void Main()
{
List<string> mylist = new List<string>();
mylist.Add("C#");
mylist.Add("Java");
mylist.Add("C");
mylist.Add("C++");
// To get an Enumerator
// for the List.
List<string>.Enumerator em = mylist.GetEnumerator();
display(em);
}
static void display(IEnumerator<string> em)
{
while (em.MoveNext()) {
string val = em.Current; // Want to know Next and Previous values of current value.
Console.WriteLine(val);
}
}
Enumerators, in the GetEnumerator() sense, are forwards-only, once-only cursors over data. If you want to know the next value: use MoveNext() and look. If you want to know what the previous value was: you should have remembered it. Since most data structures are not doubly-linked lists, and since enumerators are not even necessarily based on data that is stored anywhere (you can do some really interesting things with iterator blocks), nothing else is possible.
In the specific case of List<T>: perhaps use a for loop instead of your foreach-like enumerator access, and then you can just use list[i-1] and list[i+1] (after checking your boundary conditions).
Note: as a general rule, you should avoid using the enumerator APIs directly unless you are very, very familiar with what is going on underneath. Prefer foreach or indexer-based access.
You could generalize a triplet (previous/current/next) iterator with your own iterator block; the output from { 1, 4, 5, 1, 543, 2, 1, 54, 23 }
is:
1-4-5
4-5-1
5-1-543
1-543-2
543-2-1
2-1-54
1-54-23
Code:
using System;
using System.Collections.Generic;
public static class Program
{
static void Main()
{
var data = new List<int> { 1, 4, 5, 1, 543, 2, 1, 54, 23 };
foreach(var t in data.Tripletize())
{
Console.WriteLine($"{t.Previous}-{t.Current}-{t.Next}");
}
}
static IEnumerable<Triplet<T>> Tripletize<T>(this IEnumerable<T> source)
{
using (var iter = source.GetEnumerator())
{
// read the first triple
if (!iter.MoveNext()) yield break;
var x = iter.Current;
if (!iter.MoveNext()) yield break;
var y = iter.Current;
if (!iter.MoveNext()) yield break;
var z = iter.Current;
yield return new Triplet<T>(x, y, z);
while (iter.MoveNext())
{
x = y;
y = z;
z = iter.Current;
yield return new Triplet<T>(x, y, z);
}
}
}
readonly struct Triplet<T>
{
public Triplet(T previous, T current, T next)
{
Previous = previous;
Current = current;
Next = next;
}
public T Previous { get; }
public T Current { get; }
public T Next { get; }
}
}
IEnumerable does not support checking the previous and next items. It provides access only to the current item. If you want to track the previous item you should store it manually in a local variable. Or you should store two previous values and pretend that the current one is the next.
static void display(IEnumerator<string> em)
{
if (!em.MoveNext())
return;
string prev = null; // store prev
string current = null; // store current
string next = em.Current; // null <- null -> next
do
{
// move 'window' further so that next becomes current
prev = current;
current = next;
next = em.MoveNext() ? em.Current : null;
Console.WriteLine($"[{prev}] <-[{current}]-> [{next}]");
}
while (next != null);
}
Output with your test data:
"[] <-[C#]-> [Java]"
"[C#] <-[Java]-> [C]"
"]Java] <-[C]-> [C++]"
"[C] <-[C++]-> []"
But there is a data type with required functionality from the box - doubly linked list
var mylist = new LinkedList<string>(); // instead of List
mylist.AddLast("C#");
mylist.AddLast("Java");
mylist.AddLast("C");
mylist.AddLast("C++");
display(mylist );
And here you go
static void display(LinkedList<string> list)
{
var current = list.First;
while (current != null)
{
string val = current.Value;
// null if there is no next/prev value, but you can just check if node exists
string prev = current.Previous?.Value;
string next = current.Next?.Value;
Console.WriteLine(val);
current = current.Next;
}
}
Use Something like this :
class Program
{
int position = -1;
public List<string> mylist;
public bool MoveNext()
{
position++;
return (position < mylist.Count);
}
public String GetCurrent
{
get
{
return Current;
}
}
public string GetPrevious
{
get
{
return Previous;
}
}
public String Previous
{
get
{
try
{
return mylist[position-1];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
public String Current
{
get
{
try
{
return mylist[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
void Main(string[] args)
{
mylist = new List<string>();
mylist.Add("C#");
mylist.Add("Java");
mylist.Add("C");
mylist.Add("C++");
display(mylist);
}
void display(List<string> em)
{
while (MoveNext())
{
string val = GetCurrent;
string val2 = GetPrevious;
Console.WriteLine(val);
}
}
}

Be able to show the next value in a Linked List by clicking a button

This is probably a simple task however I am unable to solve.
So currently I have set up a form which contains a textbox and a button and I want to be able to click the button and the first value within the LinkedList will show up in the textbox. If I click the button again then the next value will show up etc.
I currently go it so that the first value will show up but then I am unable to proceed to the next value.
This is the code I have currently:
public class Node
{
public string data;
public Node next;
public Node(string newData)
{
data = newData;
next = null;
}
public void AddEnd(string data)
{
if (next == null)
{
next = new Node(data);
}
else
{
next.AddEnd(data);
}
}
}
public class myList
{
public void AddEnd(string data)
{
if (headnode == null)
{
headnode = new Node(data);
}
else
{
headnode.AddEnd(data);
}
}
public string getFirst() // this gets the first value within the list and returns it
{
if (headnode == null)
{
throw new Exception("List is empty");
}
Node node = headnode;
while (node.next != null)
{
node = node.next;
}
return node.data;
}
I also tried using this:
public class NavigationList<T> : List<T>
{
private int _currentIndex = -1;
public int CurrentIndex
{
get
{
if (_currentIndex == Count)
_currentIndex = 0;
else if (_currentIndex > Count - 1)
_currentIndex = Count - 1;
else if (_currentIndex < 0)
_currentIndex = 0;
return _currentIndex;
}
set { _currentIndex = value; }
}
public T MoveNext
{
get { _currentIndex++; return this[CurrentIndex]; }
}
public T Current
{
get { return this[CurrentIndex]; }
}
}
However, I am not really familiar with something like this so I wasn't sure on how to use it.
So you have a sequence of items, and the only thing that you want, is to get the first item, and once you've got an item, every time your ask for it, you want the next item, until there are no more items left.
In .NET this is called an IEnumerable, or if you know what kind of items are in your sequence, for instance items of MyClass, it is called an IEnumerable<MyClass>. In your case you need an IEnumerable<string>.
Luckily .NET is loaded with classes that implement IEnumerable. Two of the most used ones are array and list. You seldom have to create an enumerable class yourself, re-use the existing ones and enumerate over it.
List<string> myData = ... // fill this list somehow.
IEnumerator<string> myEnumerator = null // we are not enumerating yet.
string GetNextItemToDisplay()
{ // returns null if there are no more items to display
// if we haven't started yet, get the enumerator:
if (this.myEnumerator == null) this.myEnumerator = this.myData.GetEnumerator();
// get the next element (or if we haven't fetched anything yet: get the first element
// for this we use MoveNext. This returns false if there is no next element
while (this.myEnumerator.MoveNext())
{
// There is a next string. It is in Current:
string nextString = enumerator.Current();
return nextString;
}
// if here: no strings left. return null:
return null;
}
This looks like a lot of code, but if you remove the comments it is in fact just a few lines of code:
string GetNextItemToDisplay()
{
if (this.myEnumerator == null) this.myEnumerator = this.myData.GetEnumerator();
while (this.myEnumerator.MoveNext())
return enumerator.Current();
return null;
}
Your ButtonClick event handler:
void OnButtonClick(object sender, eventArgs e)
{
string nextItemToDisplay = this.GetNextItemToDisplay();
if (nextItemToDisplay != null)
this.Display(nextItemToDisplay);
else
this.DisplayNoMoreItems():
}
If you want to start over again with the first element, for instance after changing the List
void RestartEnumeration()
{
this.myEnumerator = null;
}

How to get a certain part of a linked list

I have a project at my university and I stumbled upon a problem I am not able to solve.
About the program: I need to create a list of tasks(they can be private or business tasks). I need a function that returns a list of ONLY private tasks and another function that returns a list of ONLY business tasks.
So I have a class "Task" that contains "next" and "prev" connections. The classes "PrivateTask" and "BusinessTask" inherit this class. I also have a class ToDoList where I actually try to create the list.
class ToDoList
{
Task first = null;
Task last = null;
//adds new tasks and sorts them right away
public void AddSorted(Task newTask)
{
if(first == null)
{
first = newTask;
last = newTask;
}
else
{
if(newTask < first)
{
Prepend(newTask);
}
else if(newTask > last)
{
Append(newTask);
}
else
{
Task loopTask = first;
while(newTask > loopTask)
{
loopTask = loopTask.next;
}
AddBefore(loopTask, newTask);
}
}
}
//adds a new task before another chosen task
private void AddBefore(Task Next, Task newTask)
{
newTask.prev = Next.prev;
newTask.next = Next;
Next.prev.next = newTask;
Next.prev = newTask;
}
//adds at the start of the list
private void Prepend(Task newTask)
{
first.prev = newTask;
newTask.next = first;
first = newTask;
}
//adds at the end of the list
private void Append(Task newTask)
{
last.next = newTask;
newTask.prev = last;
last = newTask;
}
And now I need to return a list of BusinessTasks
//returns a list of business tasks
public ToDoList GetBusinessList()
{
ToDoList busList = new ToDoList();
Task loopTask = first;
while(loopTask != null)
{
if(loopTask is BusinessTask)
{
busList.AddSorted(loopTask);
}
loopTask = loopTask.next;
}
return busList;
}
But when I return this list the whole content of the main list synchronizes with this one and I cannot understand why.
You aren't putting copies of your tasks into your new list, you are putting references into the new list. As a result, you are changing the same objects. So when you push an item from your first list into the second list and as a result next and/or prev gets changed, you are changing both lists.
So you need to copy the item from your original list and put the new item in the second list.
while(loopTask != null)
{
if(loopTask is BusinessTask)
{
var clone = loopTask.Clone();
busList.AddSorted(clone);
}
loopTask = loopTask.next;
}
Now obviously you'll need to implement a Clone method that will copy all the properties except those that relate to the position in the list (prev and next) to a new instance of BusinessTask
Now if you actually want to have the object in both lists to be references to the same object. So that changing a property on one will change the other, then you can get clever by separating out the data part from the list node part. So you could do something like:
public class TaskBase
{
public string SomeProperty { get; set; }
}
public class Node
{
public TaskBase Data { get; private set;}
public Node Next { get; set; }
public Node Prev { get; set; }
public Node(TaskBase data)
{
Data = data;
}
public Node Clone()
{
// Now all the data part is the same object
// so changing Data.SomeProperty in one list will be
// reflected in both. But the Next and Prev properties
// are independent.
return new Node(Data);
}
}
And then your loop might look like this:
while(loopTask != null)
{
if(loopTask.Data is BusinessTask) // assuming BusinessTask derives from BaseTask
{
var clone = loopTask.Clone();
// clone contains the same BusinessTask, but it's position in the new list
// won't mess up the old list.
busList.AddSorted(clone);
}
loopTask = loopTask.next;
}

generic methods with observablecollections

This is for a Windows 8.1 Store app using .Net 4.5
I found myself replicating the same code for each "object" that I have. So I'm trying to create a more generic method to get all the data the way I want. Originally everything was <Typed> to my different objects but now I'm trying to use the generic <Object>.
public async Task<ObservableCollection<object>>selectAll()
{
var Items = await Win8StorageHelper.LoadData("person.dat", typeof(ObservableCollection<object>));
ObservableCollection<object> ItemsList = new ObservableCollection<object>();
if (typeof(Int32) == Items.GetType())
{
//Not Needed anymore
}
else
{
ItemsList = (ObservableCollection<object>)Items;
}
_list.Clear();
foreach (object item in ItemsList)
{
_list.Add(item);
}
return _list;
}
I have my original collection _frequencyList and now a new generic collection _list:
private ObservableCollection<win8Chores.Model.databaseTables.Frequency> _frequencyList;
public ObservableCollection<Object> _list = new ObservableCollection<Object>();
I'm trying to call my new method like this:
_frequencyList = await selectAll();
However, I'm getting an error:
Cannot implicitly convert type
'System.Collections.ObjectModel.ObservableCollection' to
'System.Collections.ObjectModel>observableCollection'
What do I need to do to get this code to work? Am I even on the right track? Any help is appreciated.
Update:
These are the original methods I was trying to refactor for the generic example:
public async Task<ObservableCollection<Person>> selectAllPersons()
{
var personItems = await Win8StorageHelper.LoadData("person.dat", typeof(ObservableCollection<Person>));
ObservableCollection<Person> personItemsList = new ObservableCollection<Person>();
if (typeof(Int32) == personItems.GetType())
{
//Not Needed anymore
}
else
{
personItemsList = (ObservableCollection<Person>)personItems;
}
_personList.Clear();
foreach (Person item in personItemsList)
{
_personList.Add(item);
}
return _personList;
}
public async Task<ObservableCollection<Frequency>> selectAllFrequencies()
{
var frequencyItems = await Win8StorageHelper.LoadData("frequency.dat", typeof(ObservableCollection<Frequency>));
ObservableCollection<Frequency> frequencyItemsList = new ObservableCollection<Frequency>();
if (typeof(Int32) == frequencyItems.GetType())
{
//Not Needed anymore
}
else
{
frequencyItemsList = (ObservableCollection<Frequency>)frequencyItems;
}
_frequencyList.Clear();
foreach (Frequency item in frequencyItemsList)
{
_frequencyList.Add(item);
}
return _frequencyList;
}
public async Task<ObservableCollection<Chore>> selectAllChores()
{
var choreItems = await Win8StorageHelper.LoadData("chore.dat", typeof(ObservableCollection<Chore>));
ObservableCollection<Chore> choreItemsList = new ObservableCollection<Chore>();
if (typeof(Int32) == choreItems.GetType())
{
//Not Needed anymore
}
else
{
choreItemsList = (ObservableCollection<Chore>)choreItems;
}
_choreList.Clear();
foreach (Chore item in choreItemsList)
{
_choreList.Add(item);
}
return _choreList;
}
I think you should be using generics for this; see Introduction to C# Generics
public async Task<ObservableCollection<T1>> selectAll<T1>(string filename)
{
var Items = await Win8StorageHelper.LoadData(filename, typeof(ObservableCollection<T1>));
if (Items is ObservableCollection<T1>)
{
return ((ObservableCollection<T1>)Items).ToList();
}
else
{
// empty or not the right type; depending on what the storage helper gives us
return new ObservableCollection<T1>();
}
}
called by
var personList = selectAll<Person>("person.dat");
var frequencyList = selectAll<Person>("frequency.dat");
You need something like this
public async Task<ObservableCollection<T>> selectAllItems<T>(ObservableCollection<T> _list)
{
var items = await Win8StorageHelper.LoadData(string.Format("{0}.dat",typeof(T).Name.ToLower()), typeof(ObservableCollection<T>));
_list.Clear();
if(!(items is ObservableCollection<T>))
{
return _list;
}
ObservableCollection<T> itemsList = (ObservableCollection<T>)items;
foreach (T item in itemsList)
{
_list.Add(item);
}
return _list;
}
_list is the parameter where you need to add all the items.
Then call it like
selectAllItems(_personList);
selectAllItems(_frequencyList); //etc

Return all the fields from a class

I am attempting to cycle through the Fields in my class, place the fields of a certain type into a list and then return that list. I know I am missing some key component but I cannot figure out what I am doing wrong. This is what I have so far:
...
I need to return a list of the actual fields as pointers, not a copy of the data. Any help in getting this to work would be appreciated.
I removed the above code (you should still be able to see it in the history) because it was confusing. This is the updated code (with some extra stuff removed) that works thanks to the answer from competent_tech:
string prop1;
BaseClass prop2;
SubClass prop3;
SubClass prop4;
public List<BaseClass> GetData()
{
List<BaseClass> DataList = new List<BaseClass>();
foreach (System.Reflection.PropertyInfo thisInfo in this.GetType().GetProperties())
{
var tempPropery = thisInfo.GetValue(this, null);
if (tempPropery.GetType().IsSubclassOf(typeof(BaseClass)) || tempPropery.GetType().Equals(typeof(BaseClass)))
{
DataList.Add((BaseClass)tempPropery);
};
}
return DataList;
}
The above code will allow you to get all the properties of a specific base type from your class and return them in a list. So the above code would return prop2 - prop4.
You can accomplish this through reflection.
foreach (System.Reflection.PropertyInfo oProperty in this.GetType().GetProperties()) {
}
There are numerous ways that you can use this information once you have it or filter the properties (for example, by adding an attribute to the properties that you want to collect).
You can get more information from MSDN.
Note that this code specifically references properties, but there are equivalent methods for retrieving fields (GetFields) and all members (GetMembers).
Once you have the PropertyInfo, you can call the GetValue method:
foreach (System.Reflection.PropertyInfo oProperty in this.GetType().GetProperties()) {
Console.WriteLine(oProperty.Name + " = " + oProperty.GetValue(this, null).ToString());
}
Alternatively, if you are looking at both fields and properties:
foreach (System.Reflection.MemberInfo oMember in this.GetType().GetMembers())
{
switch (oMember.MemberType)
{
case System.Reflection.MemberTypes.Field:
var oField = (System.Reflection.FieldInfo)oMember;
Console.WriteLine(oField.Name + " = " + oField.GetValue(this).ToString());
break;
case System.Reflection.MemberTypes.Property:
var oProperty = (System.Reflection.PropertyInfo)oMember;
Console.WriteLine(oProperty.Name + " = " + oProperty.GetValue(this, null).ToString());
break;
}
}
You can store data in Dictionary. For every property only set/get value from dictionary.
Something like this:
public class MyData {
private Dictionary<string, object> myData;
public MyData {
this.myData = new Dictionary<string, object>();
}
public decimal LastVersion { get { return (decimal)this.myData["LastVersion"]; } private set { this.myData["LastVersion"] = value; } }
public PrimaryAbility STR { get { return (PrimaryAbility)this.myData["STR"]; } private set { this.myData["STR"] = value; } }
public PrimaryAbility DEX { get { return (PrimaryAbility)this.myData["DEX"]; } private set { this.myData["DEX"] = value; } }
public PrimaryAbility CON { get { return (PrimaryAbility)this.myData["CON"]; } private set { this.myData["CON"] = value; } }
public PrimaryAbility INT { get { return (PrimaryAbility)this.myData["INT"]; } private set { this.myData["INT"] = value; } }
public PrimaryAbility WIS { get { return (PrimaryAbility)this.myData["WIS"]; } private set { this.myData["WIS"] = value; } }
public PrimaryAbility CHA { get { return (PrimaryAbility)this.myData["CHA"]; } private set { this.myData["CHA"] = value; } }
public DerivedAbility HP { get { return (DerivedAbility)this.myData["HP"]; } private set { this.myData["HP"] = value; } }
public DerivedAbility MP { get { return (DerivedAbility)this.myData["MP"]; } private set { this.myData["MP"] = value; } }
public DerivedAbility SP { get { return (DerivedAbility)this.myData["SP"]; } private set { this.myData["SP"] = value; } }
public DerivedAbility AC { get { return (DerivedAbility)this.myData["AC"]; } private set { this.myData["AC"] = value; } }
}
Some day I found this: "Enum.GetValues(typeof(TvStations))", maybe you should search some like this.

Categories

Resources