so I am trying to learn and practice binary search but unfortunately can not understand how binary search could work for a List of objects or just strings for example. It does not look that complicated when you deal with numbers. But how do u actually perform a binary search for instance with list of object which holds property name inside as a string value.
Binary search assumes sorted collection. So, you have to provide a compare(a,b) function. That function will return -1,0 or 1 as the result of the comparison. The function implementation for numbers or chars is trivial. But, you can implement a much more complex logic that takes one or more object properties into consideration. As long as you provide that function, you can sort any collection of the objects and you can apply binary search on that collection.
You would do it the same way as with numbers, the only difference is, that you access the property of the instance you are looking at.
For example items[x].Value instead of items[x].
Say you have a list of friends which use the Friend Class and you want to use a binary search to find if a friends exists in this list. Firstly, a binary search should only be conducted on a sorted list. Using lambda, you can order the list and then change it to an array. In this example I am collecting the input into from a textbox (which is looking for the name of the friend) after a button is clicked and then conducting the binary search. The Friend class must also implement IComparable.
class Friend : IComparable<Friend>
{
public string Name { get; set; }
public string Likes { get; set; }
public string Dislikes { get; set; }
public int Birthday { get; set; }
//Used for the binary search
public int CompareTo(Friend other)
{
return this.Name.CompareTo(other.Name);
}
}
class MainWindow
{
List<Friend> friends = new List<Friend>();
//other functions here populated the list
private void OnButtonClick(object sender, EventArgs e)
{
Friend[] sortedArray = friends.OrderBy(f => f.Name).ToArray();
int index = Array.BinarySearch(sortedArray, new Friend() { Name = tb_binarySearch.Text });
if (index < 0)
{
Console.WriteLine("Friend does not exist in list");
}
else
{
Console.WriteLine("Your friend exists at index {0}", index);
}
}
}
If the index returns as a negative number, the object does not exist. Otherwise it will be the index of the object in the sorted list.
Related
So i Have a temporary ListObject List used just to check the condition
class ListObject
{
public string Key { get; set; }
public int Value { get; set; }
public void Convert(string str)
{
Key = str;
}
}
and I'm writing a method supposed to check which name appears most times in another List of objects. The ListObject.Key gets the name assigned, while ListObject.Value stores the number of appearances. I want to check if the name was already stored from the List I'm holding the value in, and if yes, then increase the Value on the ListObject field which stores the name.
The thing is that i have no idea how to point the field which should be increased. I would need something like list[*index of the wanted name].Value += 1; How am i supposed to point the index? And should I use KeyValue pair instead of my ListObject class?
It looks like you're trying to re-invent a Dictionary<TKey,TValue>
var frequencyMap = new Dictionary<string,int>();
foreach(string item in itemList)
{
if (!frequencyMap.ContainsKey(item))
frequencyMap.Add(item, 0);
frequencyMap[item] += 1;
}
I am having a little trouble designing an efficient data storage method of storing some bookmark elements for a word automation project. Here is what i need to do. I need to get all the bookmarkstart and bookmark end and the bookmark id stored in a neat data structure that lets me access any one of these three objects given one of them with the least runtime complexity. If for example i didnt need the id to be stored, i could just make a dictionary and use the bookmark start as a key and the bookmark end as a value to have an access time of O(1). But is there a logical, simple and efficient structure to have this functionalty with all three of these items coupled together?
Thanks
If bookmark start and bookmark end are both zero based integers, you could store them in simple arrays. If you use a dictionary, then it's no longer O(1), but very close to it.
Create a basic object with the 3 fields, then have 2 arrays as indices to the actual data.
public class Bookmark
{
public int ID { get; set; }
public int Start { get; set; }
public int End { get; set; }
}
// setting up your bookmark indices
const int NumBookmarks = 200;
Bookmark[] startIndices = new Bookmark[NumBookmarks];
Bookmark[] endIndices = new Bookmark[NumBookmarks];
// add a new bookmark
Bookmark myBookmark = new Bookmark(){ID=5, Start=10, End=30};
startIndices[myBookmark.Start] = myBookmark;
endIndices[myBookmark.End] = myBookmark;
// get a bookmark
Bookmark myBookmark = startIndices[10];
Of course using an array is probably the least flexible, but will be the fastest.
If you don't need absolute speed, you can create a List, and use the Find method.
Bookmark myBookmark = myBookmarks.Find(x=>x.Start==10);
It is called a DTO:
public class Bookmark
{
public int Id { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
You can store those bookmarks in a dictionary:
var dict = new Dictionary<int, Bookmark>();
dict[bookmark.Id] = bookmark;
You are looking at implementing a customized Map/Hash/Dictionary class for this purpose.
Basically:
class BookmarkObj { /* similar to steven's */ }
class BookmarkStore {
Dictionary<int, BookmarkObj> byId;
Dictionary<DateTime, BookmarkObj> byStartDate;
Dictionary<DateTime, BookmarkObj> byEndDate;
/* Boring init code */
public void Insert(BookmarkObj obj) {
byId[obj.Id] = obj;
byStartDate[obj.Start] = obj;
byEndDate[obj.End] = obj;
}
public BookmarkObj GetById(int id) {
return byId[obj.Id];
}
/* And so on */
}
This data structure doesn't really map onto IDictionary, but you could maybe make it implement ICollection if iteration, and contracts are important to you.
If the O(1) lookup is not sooo important, you could alternatively just implement this as an List and do lookups using LINQ and simplify your life a bit. Remember, premature optimization is bad.
I have a Collection of type string that can contain any number of elements.
Now i need to find out all those elements that are duplicating and find out only the first occurance of duplicating elements and delete rest.
For ex
public class CollectionCategoryTitle
{
public long CollectionTitleId { get; set; }
public bool CollectionTitleIdSpecified { get; set; }
public string SortOrder { get; set; }
public TitlePerformance performanceField { get; set; }
public string NewOrder { get; set; }
}
List<CollectionCategoryTitle> reorderTitles =
(List<CollectionCategoryTitle>)json_serializer
.Deserialize<List<CollectionCategoryTitle>>(rTitles);
Now i need to process this collection in such a way tat it removes duplicates but it must keep the 1st occurance.
EDIT:
I have updated the code and i need to compare on "NewOrder " property
Thanks
For your specific case:
var withoutDuplicates = reorderTitles.GroupBy(z => z.NewOrder).Select(z => z.First()).ToList();
For the more general case, Distinct() is generally preferable. For example:
List<int> a = new List<int>();
a.Add(4);
a.Add(1);
a.Add(2);
a.Add(2);
a.Add(4);
a = a.Distinct().ToList();
will return 4, 1, 2. Note that Distinct doesn't guarantee the order of the returned data (the current implementation does seem to return them based on the order of the original data - but that is undocumented and thus shouldn't be relied upon).
Use the Enumerable.Distinct<T>() extension method to do this.
EDIT: mjwills correctly points out that guaranteed ordering is important in the question, so the other two suggestions are not spec-guaranteed to work. Leaving just the one that gives this guarantee.
private static IEnumerable<CollectionCategoryTitle> DistinctNewOrder(IEnumerable<CollectionCategoryTitle> src)
{
HashSet<string> seen = new HashSet<string>();
//for one last time, change for different string comparisons, such as
//new HashSet<string>(StringComparer.CurrentCultureIgnoreCase)
foreach(var item in src)
if(seen.Add(item.NewOrder))
yield return item;
}
/*...*/
var distinctTitles = reorderTitles.DistinctNewOrder().ToList();
Finally, only use .ToList() after the call to DistinctNewOrder() if you actually need it to be a list. If you're going to process the results once and then do no further work, you're better off not creating a list which wastes time and memory.
I'm working on a personal project for a friend and have hit a bit of a roadblock. I can continue as I am and write some really redundant code, but I feel there must be a more efficient way of doing this.
What I'm trying to do is write a method that will add three values and display the results to the text box under "Skill Modifier" header (see screenshot). I need to get the method, or a series of methods, to do that for each skill. It needs to get the Skill Modifier value for Balance, Climb, Escape Artist, etc...
The method would be something like "CalculateSM"
What I have currently:
private void btnUpdate_Click(object sender, EventArgs e)
{
//AM + R + MM =SM
//AM = Ability Modifier
//R = Rank
//MM = Misc Modifier
//SM = Skill Modifier
decimal balanceMod = balanceAM.Value + balanceR.Value + balanceMM.Value;
balanceSM.Text = balanceMod.ToString();
decimal climbMod = climbAM.Value + climbR.Value + climbMM.Value;
climbSM.Text = climbMod.ToString();
//etc...
}
Essentially the biggest issue, for me, is figuring out how to contrive a method that can deal with so many different field names and add them in the same way. I'd like to avoid copy and pasting the same two lines of code fifty times over for each and every skill.
Any ideas would be much appreciated! Thank you.
using fields like this is not very object-oriented. you're probably going to want to introduce a Skills class that implements the method to calculate the final skill score and then use some Skills objects for different skills.
public class Skill
{
int ability, rank, misc;
public Skill(int ability, int rank, int misc)
{
this.ability = ability;
this.rank = rank;
this.misc = misc;
}
public int Score { get { return ability + rank + misc; }
}
Skill balance = new Skill(10, 1, 1);
textBalance.Text = balance.Score.ToString();
Skill programming = new Skill(10, 100, 0);
textProgramming.Text = programming.Score.ToString();
also, think of a clever way to tie the skills to your user controls. you're not going to like ending up with 50 text boxes that are all alike except for a bit of a name. a first step could be to wire them all up to the same event handler, for example.
Normally, the approach would be to create a class which represents one row of your skills screen. You could then keep a list of these in some way (say, List<Skill>). You could then quite easily loop through all of them:
foreach (Skill skill in character.Skills)
{
// do something with the skill object
}
The trick would be to dynamically generate the user interface. It's not actually very hard to do this (although a bit too much code to go into here), by far the easiest approach would be to use something like a DataGridView. It should be fairly easy to google for examples, or just ask if you want specific info.
Looks like you have an object collection which you could databind to something in the UI (like a data grid or something)
Modify the values calculate things, what you could do in some example code:
class Skill
{
public string Name { get; set; }
public string KeyAbility { get; set; }
public int SkillModifier { get; set; }
public int AbilityModifier { get; set; }
public int Ranks { get; set; }
public int MiscModifier { get; set; }
void Calculate()
{
//Formula goes here
//Set the SkillModifier
}
}
Skill balance = new Skill() { Name = "Balance" }
Basically you can make a collection of skills, update through what ever UI object you bind to etc. Using fields the way you are atm is very redundant and using OO you can achieve the same with alot less work.
Basically in You'd create a collection of the Skill class, with Balance and all other skills you mentioned. Databind this collection to something in the UI, allow for updating, call different methods. You could even implement some inheritance for different type of skills. With a Skill base class.
What type are balanceAM, balanceR etc?
Can they not derive from a base type or interface that you can use to pass to a helper method?
private string GetText(IModel modelAM, IModel modelR, IModel modelMM)
{
return modelAM.Value + modelR.Value + modelMM.Value;
}
balanceSM.Text = this.GetText(balanceAM, balanceR, balanceMM);
Ok, the fact that you only have private fields for each individual control is your core problem. You're probably better off creating a list of structs to store them:
struct PickYourOwnNameHere
{
Control SM;
Control AM;
Control R;
Control MM;
}
List<PickYourOwnNameHere> skills = new List<PickYourOwnNameHere>();
Obviously, populate that list on initialization, and then you can just do:
skills.ForEach(skill =>
skill.SM.Text = (skill.AM.Value + skill.R.Value + skill.MM.Value).ToString()
);
I'm doing that syntax from memory, but hopefully you get the idea.
I have a problem with how the List Sort method deals with sorting. Given the following element:
class Element : IComparable<Element>
{
public int Priority { get; set; }
public string Description { get; set; }
public int CompareTo(Element other)
{
return Priority.CompareTo(other.Priority);
}
}
If I try to sort it this way:
List<Element> elements = new List<Element>()
{
new Element()
{
Priority = 1,
Description = "First"
},
new Element()
{
Priority = 1,
Description = "Second"
},
new Element()
{
Priority = 2,
Description = "Third"
}
};
elements.Sort();
Then the first element is the previously second element "Second". Or, in other words, this assertion fails:
Assert.AreEqual("First", elements[0].Description);
Why is .NET reordering my list when the elements are essentially the same? I'd like for it to only reorder the list if the comparison returns a non-zero value.
From the documentation of the List.Sort() method from MSDN:
This method uses Array.Sort, which uses the QuickSort algorithm. This implementation performs an unstable sort; that is, if two elements are equal, their order might not be preserved. In contrast, a stable sort preserves the order of elements that are equal.
Here's the link:
http://msdn.microsoft.com/en-us/library/b0zbh7b6.aspx
Essentially, the sort is performing as designed and documented.
Here is an extension method SortStable() for List<T> where T : IComparable<T>:
public static void SortStable<T>(this List<T> list) where T : IComparable<T>
{
var listStableOrdered = list.OrderBy(x => x, new ComparableComparer<T>()).ToList();
list.Clear();
list.AddRange(listStableOrdered);
}
private class ComparableComparer<T> : IComparer<T> where T : IComparable<T>
{
public int Compare(T x, T y)
{
return x.CompareTo(y);
}
}
Test:
[Test]
public void SortStable()
{
var list = new List<SortItem>
{
new SortItem{ SortOrder = 1, Name = "Name1"},
new SortItem{ SortOrder = 2, Name = "Name2"},
new SortItem{ SortOrder = 2, Name = "Name3"},
};
list.SortStable();
Assert.That(list.ElementAt(0).SortOrder, Is.EqualTo(1));
Assert.That(list.ElementAt(0).Name, Is.EqualTo("Name1"));
Assert.That(list.ElementAt(1).SortOrder, Is.EqualTo(2));
Assert.That(list.ElementAt(1).Name, Is.EqualTo("Name2"));
Assert.That(list.ElementAt(2).SortOrder, Is.EqualTo(2));
Assert.That(list.ElementAt(2).Name, Is.EqualTo("Name3"));
}
private class SortItem : IComparable<SortItem>
{
public int SortOrder { get; set; }
public string Name { get; set; }
public int CompareTo(SortItem other)
{
return SortOrder.CompareTo(other.SortOrder);
}
}
In the test method, if you call Sort() method instead of SortStable(), you can see that the test would fail.
You told it how to compare things and it did. You should not rely on internal implementation of Sort in your application. That's why it let's you override CompareTo. If you want to have a secondary sort parameter ("description" in this case), code it into your CompareTo. Relying on how Sort just happens to work is a great way to code in a bug that is very difficult to find.
You could find a stable quicksort for .NET or use a merge sort (which is already stable).
See the other responses for why List.Sort() is unstable. If you need a stable sort and are using .NET 3.5, try Enumerable.OrderBy() (LINQ).
You can fix this by adding an "index value" to your structure, and including that in the CompareTo method when Priority.CompareTo returns 0. You would then need to initialize the "index" value before doing the sort.
The CompareTo method would look like this:
public int CompareTo(Element other)
{
var ret = Priority.CompareTo(other.Priority);
if (ret == 0)
{
ret = Comparer<int>.Default.Compare(Index, other.Index);
}
return ret;
}
Then instead of doing elements.Sort(), you would do:
for(int i = 0; i < elements.Count; ++i)
{
elements[i].Index = i;
}
elements.Sort();
In some applications, when a list of items is sorted according to some criterion, preserving the original order of items which compare equal is unnecessary. In other applications, it is necessary. Sort methods which preserve the arrangement of items with matching keys (called "stable sorts" are generally either much slower than those which do not ("unstable sorts"), or else they require a significant amount of temporary storage (and are still somewhat slower). The first "standard library" sort routine to become widespread was probably the qsort() function included in the standard C library. That library would frequently have been used to sort lists that were large relative to the total amount of memory available. The library would have been much less useful if it had required an amount of temporary storage proportional to the number of items in the array to be sorted.
Sort methods that will be used under frameworks like Java or .net could practically make use of much more temporary storage than would have been acceptable in a C qsort() routine. A temporary memory requirement equal to the size of the array to be sorted would in most cases not pose any particular problem. Nonetheless, since it's been traditional for libraries to supply a Quicksort implementation, that seems to be the pattern followed by .net.
If you wanted to sort based on two fields instead of one you could do this:
class Element : IComparable<Element>
{
public int Priority { get; set; }
public string Description { get; set; }
public int CompareTo(Element other)
{
if (Priority.CompareTo(other.Priority) == 0)
{
return Description.CompareTo(other.Description);
} else {
return Priority.CompareTo(other.Priority);
}
}
}
Obviously, this doesn't satisfy the requirement of a stable search algorithm; However, it does satisfy your assertion, and allows control of your element order in the event of equality.