Get data from list - c#

I have created a list which has soundfragments and contains different fragments with each a unique number.
I need to search for a unique number in the list I made (Soundfragment), if the number is found then I need to return the found number. If it isn't found then I have to return null.
How do I search for a unique number in my list?
class BGExperience
{
private List<Soundfragment> fragmenten; // = new List<Soundfragment>();
private String theme;
/******** constructoren ***************************************************/
public BGExperience(String theme)
{
fragmenten = new List<Soundfragment>();
this.theme = theme;
}
/******** properties ********************************************************/
public String Theme
{
get { return Theme; }
}
/******** methoden ********************************************************/
// returns Soundfragment with nummber nr
// if it is unkown return null
public Soundfragment GetFragment(int nr)
{
}
// returns list with all fragments
public List<Geluidsfragment> GetAlleFragmenten()
{
return fragmenten;
}

You can do the GetFragment method using linq...
var result = fragmenten.Where(s => s.NumberSoundFragment == nr).ToList();
Then you can check if result has no items, return null, and if not, just return the first item!

public Soundfragment GetFragment(int nr)
{
var sFragment = fragmenten.Where(f => f.Number == nr);
if(sFragment.Any()) return sFragment.First();
else return null;
}
I assumed your Soundfragment class has Number property.If it is different change it to your property name.
Or you can do it with one line:
public Soundfragment GetFragment(int nr)
{
return fragmenten.Where(f => f.Number == nr).FirstOrDefault();
}

Related

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;
}

Best way to find values not in two lists c#

I have two lists which I need to compare (carOptions and custOptions).
Both of these lists are in my Customer class like below:
public class CustomerDTO
{
public int CustomerId { get; set; }
//other props removed for brevity
public List<OptionDTO> SelectedCarOptions { get; set; }
public List<OptionDTO> SelectedCustomerOptions { get; set; }
}
var existingData = _myRepository.GetDataByCustomer(customerId, year);
var existingCarOptions = existingData.Select(f => f.SelectedCarOptions);
var existingCustomerOptions = existingData.Select(f => f.SelectedCustomerOptions);
existingData is an IEnumerable of CustomerDTO and then existingCarOptions and existingCustomerOptions is an IEnumerable<List<OptionDTO>>
In the method, I have a list of IEnumerable<OptionDTO> options that gets passed in. I then break this down into car or customer based on the Enum as below:
var newCarOptions = options.Where(o => o.OptionTypeID == OptionType.CarOptions);
var newCustomerOptions = options.Where(o => o.OptionTypeID == OptionType.CustomerOptions).ToList();
What I need to do is find which options are in one collection but no in the other.
I tried as below but getting an Error on the Except (I maybe need to create my own static method in that class) but I am not sure this is the best approach really?
if (existingCarOptions.Count() != newCarOptions.Count())
{
//var test = newCarOptions.Except(existingCarOptions);
}
if (existingCustomerOptions.Count() != newCustomerOptions.Count())
{
//var test2 = newCustomerOptions.Except(existingCustomerOptions);
}
Is it also quite a bit of code in the method - I could split it out into sperate methods if required but perhaps there is a simpler way I could achieve this?
I'm assuming OptionDTO has a property called Id, which uniquely identifies an option (you have to change the code accordingly if this is not the case), you may use HashSets to quickly find unmatched OptionsDTOs, while keeping the overall time cost O(n) (where n is the max number of combined options).
Create the existing options sets:
var existingCarOptions = existingData.SelectMany(d => d.SelectedCarOptions).Select(o => o.Id);
var existingCustomerOptions = existingData.SelectMany(d => d.SelectedCustomerOptions).Select(o => o.Id);
var existingCarOptionsIds = new HashSet<int>(existingCarOptions);
var existingCustomerOptionsIds = new HashSet<int>(existingCustomerOptions );
Then you extract options missing in existing sets with:
var unmatchedCarOptions = newCarOptions.Where(o => !existingCarOptionsIds.Contains(o.Id));
var unmatchedCustomerOptions = newCustomerOptions.Where(o => !existingCustomerOptionsIds.Contains(o.Id));
If you want to compare two classes you can use IEqualityComparer
public class OptionComparer : IEqualityComparer<OptionDTO>
{
public bool Equals(OptionDTO x, OptionDTO y)
{
if (object.ReferenceEquals(x, y))
{
return true;
}
if (object.ReferenceEquals(x, null) ||
object.ReferenceEquals(y, null))
{
return false;
}
return x.OptionTypeID == y.OptionTypeID ;
}
public int GetHashCode(OptionDTO obj)
{
if (obj == null)
{
return 0;
}
return obj.OptionTypeID.GetHashCode();
}
With using this you can ıdentify that What is the concept of equality for these classes.
Now we can find different values..
public List<OptionDTO>CalculateDiffBetweenLists(List<OptionDTO> left, List<OptionDTO> right){
List<OptionDTO> optionDiff;
optionDiff = left.Except(right, new OptionComparer ()).ToList();
return optionDiff ;
}

C# Sorted list without LINQ and SORT

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.

List<T> BinarySearch using a String indexer

So I have a CreditCard class that has some properties, one of which is for the card number as a String (public string Number { get; set; }). I'm storing the CreditCard objects in a CreditCardList class which has the variable List (private List<CreditCard> cclist = new List<CreditCard>();). I want to be able to retrieve a CreditCard by its card number by sorting the List first, then using the BinarySearch method on the List. I also want to do this by passing a String indexer of the number to search for into the BinarySearch method, along with a comparer if I need one.
This is what I have so far for the method to get the CreditCard matching the number, but Visual Studio 2013 gives me an error on the line: int index = cclist.BinarySearch(cclist[input], new CreditCardComparer()); "the best overloaded method match for 'System.Collections.Generic.List.this[int]' has some invalid arguments." I assume it's because I'm using the String indexer wrong or something.
public List<CreditCard> GetCardByNumber (string input)
{
List<CreditCard> tempList = new List<CreditCard>();
// save the current unsorted list to a temporary list to revert back to after sorting
List<CreditCard> originalList = new List<CreditCard>(cclist.Capacity);
for (int i = 0; i < cclist.Capacity; i++)
{
originalList[i] = cclist[i];
}
// begin sorting for binary search of card number
cclist.Sort();
int index = cclist.BinarySearch(cclist[input], new CreditCardComparer());
if (index < 0)
{
tempList.Add(cclist[input]);
}
// revert back to the original unsorted list
for (int i = 0; i < originalList.Capacity; i++)
{
cclist[i] = originalList[i];
}
// return the found credit card matching the specified number
return tempList;
}// end GetCardByNumber (string input)
Here are my int and string indexers:
public CreditCard this[int i]
{
get
{
if (i < 0 || i >= cclist.Count)
{
throw new ArgumentOutOfRangeException("index " + i + " does not exist");
}
return cclist[i];
}
set
{
if (i < 0 || i >= cclist.Count)
{
throw new ArgumentOutOfRangeException("index " + i + " does not exist");
}
cclist[i] = value;
saveNeeded = true;
}
}// end CreditCard this[int i]
public CreditCard this[string input]
{
get
{
foreach (CreditCard cc in cclist)
{
if (cc.Number == input)
{
return cc;
}
}
return null;
}
}// end CreditCard this[string number]
And here is my comparer class:
public class CreditCardComparer : IComparer<CreditCard>
{
public override int Compare(CreditCard x, CreditCard y)
{
return x.Number.CompareTo(y.Number);
}
}// end CreditCardComparer : IComparer<CreditCard>
And lastly, here are the necessities for my list sorting and what not...
class CreditCard : IEquatable<CreditCard>, IComparable<CreditCard>
{
public bool Equals (CreditCard other)
{
if (this.Number == other.Number)
{
return true;
}
else
{
return false;
}
}// end Equals(CreditCard other)
public int CompareTo(CreditCard other)
{
return Number.CompareTo(other.Number);
}// end CompareTo(CreditCard other)
}
Is it truly possible to do what I'm attempting, i.e. sending a string indexer that returns a CreditCard object based on a string into a BinarySearch method of List?
Also, I can provide any more code if necessary, but I felt like this was a little much to begin with.
A System.Collections.Generic.List uses an int as the indexer property, it does not let you use a string.
If you want to use a string as your indexer (primary key), you should probably use a Dictionary<string,CreditCard> instead.
There are a couple things amiss in your GetCardByNumber method. First is the method returns an entire list instead of a single CreditCard, which goes against the method name. Second, the binary search is not even needed since you do the searching in the string indexer first:
public CreditCard this[string input]
{
get
{
foreach (CreditCard cc in cclist)
{
if (cc.Number == input)
{
return cc;
}
}
return null;
}
}
By this point, you've already found the CreditCard with the information you need, so why search for it again in a BinarySearch? Thirdly, as was covered in landoncz's answer, you can't use a string as an index for a List<T>. What you probably intended to use was the CreditCardList instead of the List<CreditCard>
CreditCardList creditCardList = new CreditCardList();
creditCardList["1234"]; //correct
List<CreditCard> cclist = new List<CreditCard>();
cclist["1234"]; //incorrect. This is where your error is coming from.
If you're trying to access the indexer property inside of the class that implements it (which I'm assuming you are trying to do in your GetCardByNumber method), just use this[index]:
public class CreditCardList
{
public CreditCard this[string s] { /*Implementation*/ }
public CreditCard GetCard(string s)
{
return this[s]; // right here!
}
}
Now... according to your comment, "Retrieve the CreditCard with a specified number if it exists using the BinarySearch method in List<T> in the implementation of a String indexer.", it seems to me that the assignment wants you doing something along these lines. (a thing to note is that I'm not sure of your entire implementation of the CreditCard class, so please excuse the naive instantiation in the following code)
public class CreditCardList
{
private List<CreditCard> cclist = new List<CreditCard>();
public CreditCardList()
{
//For the sake of an example, let's magically populate the list.
MagicallyPopulateAList(cclist);
}
public CreditCard this[string s] /* In the implementation of a String indexer... */
{
get
{
CreditCard ccToSearchFor = new CreditCard() { Number = value };
cclist.Sort();
/* ...use the BinarySearch method... */
int index = cclist.BinarySearch(ccToSearchFor);
if (index >= 0)
return cclist[index]; /* ...to retrieve a CreditCard. */
else
throw new ArgumentException("Credit Card Number not found.");
}
}
}

Unreachable Code Detected Return Value

How to return value with this issue?
Help me please.
protected string SendState(Object ID_DIP,Object ID_SEQ,Object MODUL)
{
try
{
ViewState["ssDIP"] = ID_DIP.ToString();
ViewState["ssSEQ"] = ID_SEQ.ToString();
ViewState["ssMOD"] = MODUL.ToString();
return ID_DIP.AsString();
return ID_SEQ.AsString();
return MODUL.ToString();
}
catch (Exception)
{
return "";
}
}
You have multiple return statements, your code will not execute statements after first return statement. You can't return multiple values from your method, if you want to return multiple values you can either return List<string> for your case or create a temporary class and return its object.
In your code you are using AsString, I think you probably meant ToString
Define a class like:
public class MyReturnObject
{
public string ID_DIP { get; set; }
public string ID_SEQ { get; set; }
public string MODUL { get; set; }
}
Modify your method like:
protected MyReturnObject SendState(Object ID_DIP, Object ID_SEQ, Object MODUL)
{
try
{
ViewState["ssDIP"] = ID_DIP.ToString();
ViewState["ssSEQ"] = ID_SEQ.ToString();
ViewState["ssMOD"] = MODUL.ToString();
MyReturnObject obj = new MyReturnObject();
obj.ID_DIP = ID_DIP.ToString();
obj.ID_SEQ = ID_SEQ.ToString();
obj.MODUL = MODUL.ToString();
return obj;
}
catch (Exception)
{
return null;
}
}
first thing is u have multiple return values, so ur code wouldn't work, so u can use List<String> & to return in catch case, u could use a var at the top of method definition, like this--->
public List<string> SendState(Object ID_DIP,Object ID_SEQ,Object MODUL)
{
var returnValue = new List<string>();
try
{
ViewState["ssDIP"] = ID_DIP.ToString();
ViewState["ssSEQ"] = ID_SEQ.ToString();
ViewState["ssMOD"] = MODUL.ToString();
returnValue.add(ID_DIP.AsString());
returnValue.add(ID_DIP.AsString());
returnValue.add(MODUL.ToString());
}
catch (Exception)
{
returnValue = null;
}
return returnValue;
}
now u can use the above method like this--->
var result = SendState( params ) //<--- params r ur parameters
if(result != null)
// proceed
else
// no value found
If you want return multiple results which has the same type. I suggest you should apply coroutine pattern. Specifics at here as code below:
protected IEnumerable<string> SendState(Object ID_DIP,Object ID_SEQ,Object MODUL)
{
ViewState["ssDIP"] = ID_DIP.AsString();
ViewState["ssSEQ"] = ID_SEQ.AsString();
ViewState["ssMOD"] = MODUL.ToString();
yield return ID_DIP.AsString();
yield return ID_SEQ.AsString();
yield return MODUL.ToString();
}
You take reference the link to get more understand about coroutine pattern in C#.
In C#, methods generally return only one value. This value can be an object with multiple fields.
If you need to return multiple values from a method, you can use out parameters or return a type instance containing all the values.
As Habib suggested, returning List<string> is a good approach in your case.
You can only return a single value from a method, so of your three return statements only the first one will execute.
If you want to return multiple strings, return an array of strings:
protected string[] SendState(Object ID_DIP,Object ID_SEQ,Object MODUL) {
try {
ViewState["ssDIP"] = ID_DIP.ToString();
ViewState["ssSEQ"] = ID_SEQ.ToString();
ViewState["ssMOD"] = MODUL.ToString();
return new string[] {
ID_DIP.ToString(),
ID_SEQ.ToString(),
MODUL.ToString()
};
} catch (Exception) {
return null; // or perhaps an empty array...?
}
}
Any code that is written after the first return statement (within the same block) will not execute. In case you want to return multiple values from a method, consider using objects.

Categories

Resources