I've got a collection of object A's. Each A has a field that correlates is to an object B - of which I have another collection. In other words, each B is attached to a subset of the collection of As (but only conceptually, not in code). This field - correlating A to B - can change during the life of the system. There are system requirements that prevent changing of this structure.
If I need to repeatedly perform operations on each B's set of A's, would it be better to repeated use the Where() method on the collection of A's or create another collection that B owns and a class that manages the add and remove of the relevant items.
Let me see if i can capture this in code:
class A {
public B owner;
...
}
class B {
...
}
class FrequentlyCalledAction {
public DoYourThing(B current) {
List<A> relevantItems = listOfAllAItems.Where(x => x.owner == current).ToList()
foreach (A item in relevantItems) {
...
}
}
}
Vs:
class A {
public B owner;
...
}
class B {
public List<A> itsItems;
}
class FrequentlyCalledAction {
public void DoYourThing(B current) {
foreach (A item in current.itsItems) {
...
}
}
}
class AManager {
public void moveItem(A item, B from, B to) {
from.itsItems.remove(item);
to.itsItems.add(item);
}
}
This primarily depends on the size of the sets. If there are only a few items the overhead that comes with the solution two is bigger than the performance gain.
In this case I would use solution one since it has a better readability and is less complicated to manage.
If there are thousands of items in the set I would go for solution two. The moveItems method is an O(n) operation but it seems that there are more reads than writes in your scenario. Therefore you gain more performance through the more structured design.
In fact it all depend of the size of your collection. Sol 2 is more complex but faster for big collection while sol1 can be very fast for less than 100/1000 items or so.
Since the sets are small (~100 items) and they change often (~every 4 iterations) do this, then see if you have a problem.
public DoYourThing(B current)
{
foreach(A item in listOfAllAItems.Where(a => a.owner == current))
{
...
}
}
I don't see any point in casting the IEnumrable<A> to an IList<A>.
If this gives you a performance problem I don't think AManager is your best answer, although this could depend on how much the relationships change.
If you go for solution 2 it might be worth using a HashSet rather than a List. A HashSet is O(1) for Add & Remove whereas a List is O(1) for Add and O(n) for remove.
Another option is this which has the advantage that users of A & B don't need to remember to use AManager:
static class GlobalDictionary
{
private static Dictionary<B,HashSet<A>> dictionary = new Dictionary<B,HashSet<A>>();
public static HashSet<A> this[B obj]
{
// You could remove the set and have it check to see if a Set exists for a B
// if not you would create it.
get {return dictionary[obj];}
set {dictionary[obj] = value;}
}
}
class A
{
private B owner;
public B Owner
{
get{ return owner;}
set
{
if (owner != null) GlobalDictionary[owner].Remove(this);
owner = value;
GlobalDictionary[owner].Add(this);
}
}
}
class B
{
public B()
{
GlobalDictionary[this] = new HashSet<A>();
}
public IEnumerable<A> Children
{
get
{
return GlobalDictionary[this];
}
}
}
I haven't tried this so it's likely it'll require some tweaks but you should get the idea.
Related
I am trying to learn C# by making a simple program that shows the user sushi rolls given their desired ingredients. i.e. a user wants a roll with crab, and the program will spit out a list of sushi rolls that contain crab.
I've created a Roll class
public class Roll
{
private string name;
private List<string> ingredients = new List<string>();
}
With some getters and setters and other various methods.
In the GUI, I have some checkboxes which each call an update() method from the Control class, which will then need to check a list of rolls against a list of ingredients given by the GUI checkboxes. What I have is this
class Controller
{
static List<Roll> Rolls = new List<Roll>();
static RollList RL = new RollList();
static List<String> ingredients = new List<String>();
static Roll roll = new Roll();
}
public void update
{
foreach(Roll roll in Rolls)
{
foreach (String ingredient in ingredients)
if (!roll.checkForIngredient(ingredient))
Rolls.Remove(roll);
}
}
But a System.InvalidOperationException is thrown saying that because the collection was modified, the operation can't execute. OK, that's fair, but then what's the best way to do this? Here on Stack Overflow there's a post about removing elements from a generic list while iterating over it.
This was good and pointed me in the right direction, but unfortunately, my predicate condition simply doesn't match the top answer's.
It would have to iterate over the ingredients list, and I'm not even sure that's possible...
list.RemoveAll(roll => !roll.containsIngredient(each string ingredient in ingredients) );
shudder
I've tried the for loop, but I can't seem to get the enumeration to work either, and I wonder if it's even necessary to enumerate the class for just this method.
So I come here to try and find an elegant, professional solution to my problem. Keep in mind that I'm new to C# and I'm not all too familiar with predicate logic or enumeration on classes.
To use RemoveAll you can rewrite your condition to this:
list.RemoveAll(roll => !ingredients.All(roll.checkForIngredient));
This exploits the fact that when the compiler sees this, it will effectively rewrite it to this:
list.RemoveAll(roll => !ingredients.All(i => roll.checkForIngredient(i)));
Which is what you want. If not all the ingredients are present, remove the roll.
Now, having said that, since you say you're a beginner, perhaps you feel more comfortable keeping your loop, if you could just make it work (ie. stop crashing due to modifying the loop). To do that, just make a copy of the collection and then loop through the copy, you can do this by just modifying the foreach statement to this:
foreach(Roll roll in Rolls.ToList())
This will create a list based copy of the Rolls collection, and then loop on that. The list will not be modified, even if Rolls is, it is a separate copy containing all the elements of Rolls when it was created.
As requested in the comments, I'll try to explain how this line of code works:
list.RemoveAll(roll => !ingredients.All(roll.checkForIngredient));
The RemoveAll method, which you can see the documentation for here takes a predicate, a Predicate<T>, which is basically a delegate, a reference to a method.
This can be a lambda, syntax that creates an anonymous method, using the => operator. An anonymous method is basically a method declared where you want to use it, without a name, hence the anonymous part. Let's rewrite the code to use an anonymous method instead of a lambda:
list.RemoveAll(delegate(Roll roll)
{
return !ingredients.All(roll.checkForIngredient);
});
This is the exact same compiled code as for the lambda version above, just using the bit more verbose syntax of an anonymous method.
So, how does the code inside the method work.
The All method is an extension method, found on the Enumerable class: Enumerable.All.
It will basically loop through all the elements of the collection it is extending, in this case the ingredients collection of a single roll, and call the predicate function. If for any of the elements the predicate returns false, the result of calling All will also be false. If all the calls return true, the result will also be true. Note that if the collection (ingredients) is empty, the result will also be true.
So let's try to rewrite our lambda code, which again looked like this:
list.RemoveAll(roll => !ingredients.All(roll.checkForIngredient));
Into a more verbose method, not using the All extension method:
list.RemoveAll(delegate(Roll roll)
{
bool all = true;
foreach (var ingredient in ingredients)
if (!roll.checkForIngredient(ingredient))
{
all = false;
break;
}
return !all;
});
This now starts to look like your original piece of code, except that we're using the RemoveAll method, which needs a predicate that returns whether to remove the item or not. Since if all is false, we need to remove the roll, we use the not operator ! to reverse that value.
Since you are both new to C# but also asked for an elegant solution, I will give you an example of how to solve this using a more object-oriented approach.
First of all, any "thing" of significance should be modeled as a class, even if it has just one property. This makes it easier to extend the behavior later on. You already defined a class for Roll. I would also add a class for Ingredient:
public class Ingredient
{
private string _name;
public string Name
{
get { return _name; }
}
public Ingredient(string name)
{
_name = name;
}
}
Note the Name property which only has a getter, and the constructor which accepts a string name. This might look like unnecessary complexity at first but will make your code more straightforward to consume further down the road.
Next, we'll modify your Roll class according to this guideline and give it some helper methods that make it easier for us to check if a roll contains a certain (list of) ingredients:
public class Roll
{
private string _name;
private List<Ingredient> _ingredients = new List<Ingredient>();
public string Name
{
// By only exposing the property through a getter, you are preventing the name
// from being changed after the roll has been created
get { return _name; }
}
public List<Ingredient> Ingredients
{
// Similarly here, you are forcing the consumer to use the AddIngredient method
// where you can do any necessary checks before actually adding the ingredient
get { return _ingredients; }
}
public Roll(string name)
{
_name = name;
}
public bool AddIngredient(Ingredient ingredient)
{
// Returning a boolean value to indicate whether the ingredient was already present,
// gives the consumer of this class a way to present feedback to the end user
bool alreadyHasIngredient = _ingredients.Any(i => i.Name == ingredient.Name);
if (!alreadyHasIngredient)
{
_ingredients.Add(ingredient);
return true;
}
return false;
}
public bool ContainsIngredients(IEnumerable<Ingredient> ingredients)
{
// We use a method group to check for all of the supplied ingredients
// whether or not they exist
return ingredients.All(ContainsIngredient);
// Could be rewritten as: ingredients.All(i => ContainsIngredient(i));
}
public bool ContainsIngredient(Ingredient ingredient)
{
// We simply check if an ingredient is present by comparing their names
return _ingredients.Any(i => i.Name == ingredient.Name);
}
}
Pay attention to the ContainsIngredient and ContainsIngredients methods here. Now you can do stuff like if (roll.ContainsIngredient(ingredient)), which will make your code more expressive and more readable. You'll see this in action in the next class that I'm going to add, RollCollection.
You are modeling collections of food to pick from, presumably in the context of a restaurant menu or some similar domain. You might as well go ahead and model just that: a RollCollection. This will allow you to encapsulate some meaningful logic inside of the collection.
Again, this sort of thing tends to require some boilerplate code and may look overly complex at first, but it will make your classes easier to consume. So let's add a RollCollection:
public class RollCollection : IEnumerable<Roll>
{
private List<Roll> _rolls = new List<Roll>();
public RollCollection()
{
// We need to provide a default constructor if we want to be able
// to instantiate an empty RollCollection and then add rolls later on
}
public RollCollection(IEnumerable<Roll> rolls)
{
// By providing a constructor overload which accepts an IEnumerable<Roll>,
// we have the opportunity to create a new RollCollection based on a filtered existing collection of rolls
_rolls = rolls.ToList();
}
public RollCollection WhichContainIngredients(IEnumerable<Ingredient> ingredients)
{
IEnumerable<Roll> filteredRolls = _rolls
.Where(r => r.ContainsIngredients(ingredients));
return new RollCollection(filteredRolls);
}
public bool AddRoll(Roll roll)
{
// Similar to AddIngredient
bool alreadyContainsRoll = _rolls.Any(r => r.Name == roll.Name);
if (!alreadyContainsRoll)
{
_rolls.Add(roll);
return true;
}
return false;
}
#region IEnumerable implementation
public IEnumerator<Roll> GetEnumerator()
{
foreach (Roll roll in _rolls)
{
yield return roll;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
WhichContainIngredients is the thing we were really looking for, as it allows you to do something like this:
// I have omitted the (proper) instantiation of Rolls and ChosenIngredients for brevity here
public RollCollection Rolls { get; set; }
public List<Ingredient> ChosenIngredients { get; set; }
public void Update()
{
Rolls = Rolls.WhichContainIngredients(ChosenIngredients);
}
This is simple and clean, just the sort of thing you want to be doing in your presentation layer. The logic to accomplish your requirement is now nicely encapsulated in the RollCollection class.
EDIT: a more complete (but still simplified) example of how your Controller class might end up looking like:
public class Controller
{
private RollCollection _availableRolls = new RollCollection();
private List<Ingredient> _availableIngredients = new List<Ingredient>();
public RollCollection AvailableRolls
{
get { return _availableRolls; }
}
public List<Ingredient> AvailableIngredients
{
get { return _availableIngredients; }
}
public RollCollection RollsFilteredByIngredients
{
get { return AvailableRolls.WhichContainIngredients(ChosenIngredients); }
}
public List<Ingredient> ChosenIngredients { get; set; }
public Controller()
{
ChosenIngredients = new List<Ingredient>();
InitializeTestData();
}
private void InitializeTestData()
{
Ingredient ingredient1 = new Ingredient("Ingredient1");
Ingredient ingredient2 = new Ingredient("Ingredient2");
Ingredient ingredient3 = new Ingredient("Ingredient3");
_availableIngredients.Add(ingredient1);
_availableIngredients.Add(ingredient2);
_availableIngredients.Add(ingredient3);
Roll roll1 = new Roll("Roll1");
roll1.AddIngredient(ingredient1);
roll1.AddIngredient(ingredient2);
Roll roll2 = new Roll("Roll2");
roll2.AddIngredient(ingredient3);
_availableRolls.AddRoll(roll1);
_availableRolls.AddRoll(roll2);
}
}
I am trying to learn C# by making a simple program that shows the user
sushi rolls given their desired ingredients. i.e. a user wants a roll
with crab, and the program will spit out a list of sushi rolls that
contain crab.
Here's my solution to the given problem:
public class Roll
{
public string Name { get; set; }
private List<string> ingredients = new List<string>();
public IList<string> Ingredients { get { return ingredients; } }
public bool Contains(string ingredient)
{
return Ingredients.Any(i => i.Equals(ingredient));
}
}
You can use the LINQ extension method .Where to filter your collection of Rolls
public class Program
{
static void Main()
{
var allRolls = new List<Roll>
{
new Roll
{
Name = "Roll 1",
Ingredients = { "IngredientA", "Crab", "IngredientC" }
},
new Roll
{
Name = "Roll 2",
Ingredients = { "IngredientB", "IngredientC" }
},
new Roll
{
Name = "Roll 3",
Ingredients = { "Crab", "IngredientA" }
}
};
var rollsWithCrab = allRolls.Where(roll => roll.Contains("Crab"));
foreach (Roll roll in rollsWithCrab)
{
Console.WriteLine(roll.Name);
}
}
}
From what I see you're trying to remove all rolls that don't contain crab from your list of rolls. A better approach is to filter out those rolls that don't contain crab (using .Where), you can then use .ToList() if you need to manipulate the whole list directly rather than iterating through the collection (fetching one item at a time).
You should read up on Delegates, Iterators, Extension Methods and LINQ to better understand what's going on under the covers.
I hava a base type (A) which has two derivatives (B and C). The base type is not abstract. So, I have three objects.
The only difference between B and C is that they both have one extra different property:
B.Foo
C.Bar
Now I have conditions like this in my code:
if(myObject is B)
myDatabindB.DataSource = ((B)myReport).Foo);
else if(myObject is C)
myDatabindC.DataSource = ((C)myReport).Bar);
and in another method:
pnlSomePanel.Visible = myObject is B;
pnlSomeOtherPanel.Visible = myObject is C;
But you can imagine that when there's a new type I have to update all my if-else statements. This violates a lot of OO principles.
But the problem is that I can't think of a nice and clean solution to solve this issue.
Do you have a suggestion / idea to solve this problem?
EDIT:
If it matters, I am using the MVP pattern.
First, it's good that you asked this with only three items--it makes fixing problems much faster :). Your code's very generic, so I can only offer generic solutions.
The big goal here is to increase the encapsulation of classes A, B, and C--to make sure that anything relevant to A, B, or C is stored within those classes and not moved to, say, if-statements elsewhere.
We can move the logic for figuring out what the correct datasource is from the Controller (which is doing your binding) to your report. This method's name should be descriptive, like GetReportSubjectLine().
class A{
<snip>
public virtual SomeDataType getDataSourceForViewType(){
throw new NotImplementedException()
}
}
class B{
<snip>
public override SomeDataType getDataSourceForViewType(){
return this.Foo;
}
}
class C{
public override SomeDataType getDataSourceForViewType(){
return this.Bar;
}
}
This code will be reusable if you ever want to make different UI's that still need this type of information from your report to generate whatever graphical view you're generating.
There's no good way around the second problem you presented. We could always move the panel visibility into the reports too, but that increases coupling--how much one class is tied to another--way too much. Your reports should not be tied to a specific view.
The best solution is to add another layer of indirection--in this case, an intermediary class to handle the logic of what panels to make visible when. This way your controller doesn't have to bear the responsibility of managing panel visibilities itself.
public class PanelVisibilityManager{
ICollection<Panel> ManagedPanels {get; set;}
//
public IDictionary<System.Type, ICollection<Panel>> Switchboard {get; set;}
public void TogglePanelsFor(System.Type item){
foreach(var panel in ManagedPanels){
panel.Visible=false;
}
foreach(var panel in Switchboard[item]){
panel.Visible=true;
}
}
Hope this helps!
Strategy Pattern fits here pretty well for the first case
For the second case if you have one to one mapping of your panels you can end up with a static readonly Dictionary<Type, Panel> panels if there are many of types.
There is a tab control in WinForms to show some particular tab as well
One the ways to avoid that type of code is move decisional responability into object itself. For example:
Define somewher collection of A.
List<A> objects = new List<A>{new B(), new C()}
Instead of having if/else use foreach over collection and calll on every object a virtual method defined in A and overriden in childs, like
virtual bool ThisIsMe(A objectToCheck){}
B and C override this method by checking if objectToCheck is their type and return true or false in regard of it.
EDIT
Example:
public class A
{
public virtual bool ThisIsMe(A objectToCheck){}
public virtual object GetData{}
}
public class B : A
{
public override bool ThisIsMe(A objectToCheck)
{
return objectToCheck is B;
}
public override object GetData()
{
return this.Foo;
}
}
public class C : A
{
public override bool ThisIsMe(A objectToCheck)
{
return objectToCheck is B;
}
public override object GetData()
{
return this.Bar;
}
}
Now instead of that if/else, something like this:
foreach(A objA in objects)
{
if(objA.ThisIsMe(myObject))
{
myDatabindB.DataSource = objA.GetData();
break;
}
}
May be also substitude this with some fancy LINQ instruction.
Hope this helps.
How about a Dictionary<Type, Action>?
Then you could do something like this:
var myActors = new Dictionary<Type, Action<BaseClass>>();
myActors.Add(typeof(classA), DoSomethingWithA);
myActors.Add(typeof(classB), DoSomethingWithB);
...
Action actor;
if(myActors.TryGetValue(specialRetrievedOnlyAsBase.GetType(), actor))
{
ResetEverything();
actor(specialRetrievedOnlyAsBase);
}
else
{
// ToDo: What should happen if this type is not supported?
}
...
private void DoSomethingWithA(BaseClass)
{
var classAObject = (ClassA)BaseClass;
// ToDo: What should happen if classA arrives?
}
private void DoSomethingWithA(BaseClass)
{
var classAObject = (ClassB)BaseClass;
// ToDo: What should happen if classB arrives?
}
I'm trying to recreate the generic List collection. This is my code to Add items to the collection and Show all of them:
public class Collect<TItem>
{
public Collect<TItem> collectObject;
public TItem firstObject;
public void Add(TItem item)
{
if (collectObject == null)
{
collectObject = new Collect<TItem>();
collectObject.firstObject = item;
}
else
{
this.collectObject.Add(item);
}
}
public void Show()
{
if (firstObject != null)
Console.WriteLine(firstObject.ToString());
if (collectObject != null)
collectObject.Show();
}
You'd use this class like this:
Collect<int> test = new Collect<int>();
test.Add(2);
test.Add(10);
test.Add(30);
test.Add(3);
test.Show();
It prints all of the values above, but the first item is always 0.
0
2
10
30
3
This is because the very first firstObject variable is never assigned and gets the default value, but I can't figure out a way to get this fixed. The book I learned this assigns the first firstObject variable in a constructor that expects a TItem object, but I want to do it without using a constructor for this collection (to recreate a List)
I know this is exactly the same like how a generic List works, but I just want to understand the logic behind it. Thanks for the help.
You can make your TItem nullable, which allows your test to work. Also, you need to set the firstObject in the top instance of Collect, not the referenced one.
public class Collect<TItem> where TItem : struct
{
public Collect<TItem> collectObject;
public TItem? firstObject;
public void Add(TItem item)
{
if (collectObject == null)
{
collectObject = new Collect<TItem>();
firstObject = item;
}
else
{
this.collectObject.Add(item);
}
}
public void Show()
{
if (firstObject.HasValue)
Console.WriteLine(firstObject.ToString());
if (collectObject != null)
collectObject.Show();
}
}
OK, this is doing my head in, but I think you want to do something like:
if (collectObject == null)
{
collectObject = new Collect<TItem>();
this.firstObject = item;
}
because otherwise you are never actually assigning anythign tothe firstobject property of the object you are creating.
What you doing wrong is collectObject.firstObject = item; should be this.firstObject = item;
I think you just have to change the line:
collectObject.firstObject = item;
to
firstObject = item;
This way your custom collection will always be represented by a "head" and a "tail" - I assume this is what you are tryin' to acomplish.
In other words when adding an item, you say "If this is the first time to add, then this is my 'head' of the list, else - insert it into the 'tail' of the list". Printing is with the same idea - print the "head" and then call the tail's print method (in your code 'Show' method).
First, this is certainly not how System.Collections.Generic.List<T> works. It uses an array internally, not a singly-linked list as you do. LinkedList<T> is somewhat similar to your collection, except it uses a doubly liked list.
Now, onto your issue. The problem with your collection is that it is not able to represent an empty value and it seems you want that. What I would suggest is to create another public class that represents the whole collection and change your Collect<T> only to an internal implementation (let's call it Node<T>). This way, the new collection class can contain null reference to Node<T>, when it is first constructed, which signifies an empty collection.
If this were production code, I'm pretty sure you would actually need to do something like this, because you are going to want to keep some information on a per-collection basis (like count).
Another option (which is usually taken by lists in functional languages) is to create an inheritance hierarchy similar to the following:
abstract class Node<T>
{ }
class FullNode<T> : Node<T>
{
public T Item { get; private set; }
public Node<T> Next { get; private set }
// constructor and possibly other members
}
class EmptyNode<T> : Node<T>
{ }
This way, you have separate types to represent a full node and an empty node. In those lists, it is usual to add new items to the front, not to the back, though.
I would suggest at least one other improvement, regarding the speed of adding, but I suppose your book will get to that.
Also, I'm quite sure this is the case, but I really hope you're not planning on using this code in any kind of production environment and that it is just an learning exercise.
Just to add a little bit more information...
The reason the 0 is being written out is because you have a != null check on the firstObject. Obviously, the default value of an integer is not null, it is zero, so when firstObject hasn't been set it will be zero and not null. I guess if you want to exclude any value that is not the default for that type you could change your check to:
if (firstObject != default(TItem))
That's probably not exactly what you want though as I'm sure zero could be a valid value in this instance.
Try a nullable type
Collect<int?> test = new Collect<int?>();
As a result of another question I asked here I want to use a HashSet for my objects
I will create objects containing a string and a reference to its owner.
public class Synonym
{
private string name;
private Stock owner;
public Stock(string NameSynonym, Stock stock)
{
name=NameSynonym;
owner=stock
}
// [+ 'get' for 'name' and 'owner']
}
I understand I need a comparer , but never used it before. Should I create a separate class? like:
public class SynonymComparer : IComparer<Synonym>
{
public int Compare(Synonym One, Synonym Two)
{ // Should I test if 'One == null' or 'Two == null' ????
return String.Compare(One.Name, Two.Name, true); // Caseinsesitive
}
}
I prefer to have a function (or nested class [maybe a singleton?] if required) being PART of class Synonym instead of another (independent) class. Is this possible?
About usage:
As i never used this kind of thing before I suppose I must write a Find(string NameSynonym) function inside class Synonym, but how should I do that?
public class SynonymManager
{
private HashSet<SynonymComparer<Synonym>> ListOfSynonyms;
public SynonymManager()
{
ListOfSymnonyms = new HashSet<SynonymComparer<Synonym>>();
}
public void SomeFunction()
{ // Just a function to add 2 sysnonyms to 1 stock
Stock stock = GetStock("General Motors");
Synonym otherName = new Synonym("GM", stock);
ListOfSynonyms.Add(otherName);
Synonym otherName = new Synonym("Gen. Motors", stock);
ListOfSynonyms.Add(otherName);
}
public Synonym Find(string NameSynomym)
{
return ListOfSynonyms.??????(NameSynonym);
}
}
In the code above I don't know how to implement the 'Find' method. How should i do that?
Any help will be appreciated
(PS If my ideas about how it should be implemented are completely wrong let me know and tell me how to implement)
A HashSet doesn't need a IComparer<T> - it needs an IEqualityComparer<T>, such as
public class SynonymComparer : IEqualityComparer<Synonym>
{
public bool Equals(Synonym one, Synonym two)
{
// Adjust according to requirements.
return StringComparer.InvariantCultureIgnoreCase
.Equals(one.Name, two.Name);
}
public int GetHashCode(Synonym item)
{
return StringComparer.InvariantCultureIgnoreCase
.GetHashCode(item.Name);
}
}
However, your current code only compiles because you're creating a set of comparers rather than a set of synonyms.
Furthermore, I don't think you really want a set at all. It seems to me that you want a dictionary or a lookup so that you can find the synonyms for a given name:
public class SynonymManager
{
private readonly IDictionary<string, Synonym> synonyms = new
Dictionary<string, Synonym>();
private void Add(Synonym synonym)
{
// This will overwrite any existing synonym with the same name.
synonyms[synonym.Name] = synonym;
}
public void SomeFunction()
{
// Just a function to add 2 synonyms to 1 stock.
Stock stock = GetStock("General Motors");
Synonym otherName = new Synonym("GM", stock);
Add(otherName);
ListOfSynonyms.Add(otherName);
otherName = new Synonym("Gen. Motors", stock);
Add(otherName);
}
public Synonym Find(string nameSynonym)
{
// This will throw an exception if you don't have
// a synonym of the right name. Do you want that?
return synonyms[nameSynonym];
}
}
Note that there are some questions in the code above, about how you want it to behave in various cases. You need to work out exactly what you want it to do.
EDIT: If you want to be able to store multiple stocks for a single synonym, you effectively want a Lookup<string, Stock> - but that's immutable. You're probably best storing a Dictionary<string, List<Stock>>; a list of stocks for each string.
In terms of not throwing an error from Find, you should look at Dictionary.TryGetValue which doesn't throw an exception if the key isn't found (and also returns whether or not the key was found); the mapped value is "returned" in an out parameter.
Wouldn't it be more reasonable to scrap the Synonym class entirely and have list of synonyms to be a Dictonary (or, if there is such a thing, HashDictionary) of strings?
(I'm not very familiar with C# types, but I hope this conveys general idea)
The answer I recommend (edited, now respects the case):
IDictionary<string, Stock>> ListOfSynonyms = new Dictionary<string,Stock>>();
IDictionary<string, string>> ListOfSynForms = new Dictionary<string,string>>();
class Stock
{
...
Stock addSynonym(String syn)
{
ListOfSynForms[syn.ToUpper()] = syn;
return ListOfSynonyms[syn.ToUpper()] = this;
}
Array findSynonyms()
{
return ListOfSynonyms.findKeysFromValue(this).map(x => ListOfSynForms[x]);
}
}
...
GetStock("General Motors").addSynonym('GM').addSynonym('Gen. Motors');
...
try
{
... ListOfSynonyms[synonym].name ...
}
catch (OutOfBounds e)
{
...
}
...
// output everything that is synonymous to GM. This is mix of C# and Python
... GetStock('General Motors').findSynonyms()
// test if there is a synonym
if (input in ListOfSynonyms)
{
...
}
You can always use LINQ to do the lookup:
public Synonym Find(string NameSynomym)
{
return ListOfSynonyms.SingleOrDefault(x => x.Name == NameSynomym);
}
But, have you considered using a Dictionary instead, I believe it is better suited for extracting single members, and you can still guarantee that there are no duplicates based on the key you choose.
I am not sure that lookup time is of SingleOrDefault, but I am pretty sure it is linear (O(n)), so if lookup time is important to you, a Dictionary will provide you with O(1) lookup time.
How would you implement a capacity-limited, generic MruList in C# or Java?
I want to have a class that represents a most-recently-used cache or list (= MruList). It should be generic, and limited to a capacity (count) specified at instantiation. I'd like the interface to be something like:
public interface IMruList<T>
{
public T Store(T item);
public void Clear();
public void StoreRange(T[] range);
public List<T> GetList();
public T GetNext(); // cursor-based retrieval
}
Each Store() should put the item at the top (front?) of the list. The GetList() should return all items in an ordered list, ordered by most recent store. If I call Store() 20 times and my list is 10 items long, I only want to retain the 10 most-recently Stored items. The GetList and StoreRange is intended to support retrieval/save of the MruList on app start and shutdown.
This is to support a GUI app.
I guess I might also want to know the timestamp on a stored item. Maybe. Not sure.
Internally, how would you implement it, and why?
(no, this is not a course assignment)
Couple of comments about your approach
Why have Store return T? I know what I just added, returning it back to me is un-necessary unless you explicitly want method chaining
Refactor GetNext() into a new class. It represents a different set of functionality (storage vs. cursor traversal) and should be represented by a separate interface. It also has usability concerns as what happens when two different methods active on the same stack want to traverse the structure?
GetList() should likely return IEnumerable<T>. Returning List<T> either forces an explicit copy up front or returns a pointer to an underlying implementation. Neither is a great choice.
As for what is the best structure to back the interface. It seems like the best to implement is to have a data structure which is efficient at adding to one end, and removing from the other. A doubly linked list would suit this nicely.
Here's a Cache class that stores objects by the time they were accessed. More recent items bubble to the end of the list. The cache operates off an indexer property that takes an object key. You could easily replace the internal dictionary to a list and reference the list from the indexer.
BTW, you should rename the class to MRU as well :)
class Cache
{
Dictionary<object, object> cache = new Dictionary<object, object>();
/// <summary>
/// Keeps up with the most recently read items.
/// Items at the end of the list were read last.
/// Items at the front of the list have been the most idle.
/// Items at the front are removed if the cache capacity is reached.
/// </summary>
List<object> priority = new List<object>();
public Type Type { get; set; }
public Cache(Type type)
{
this.Type = type;
//TODO: register this cache with the manager
}
public object this[object key]
{
get
{
lock (this)
{
if (!cache.ContainsKey(key)) return null;
//move the item to the end of the list
priority.Remove(key);
priority.Add(key);
return cache[key];
}
}
set
{
lock (this)
{
if (Capacity > 0 && cache.Count == Capacity)
{
cache.Remove(priority[0]);
priority.RemoveAt(0);
}
cache[key] = value;
priority.Remove(key);
priority.Add(key);
if (priority.Count != cache.Count)
throw new Exception("Capacity mismatch.");
}
}
}
public int Count { get { return cache.Count; } }
public int Capacity { get; set; }
public void Clear()
{
lock (this)
{
priority.Clear();
cache.Clear();
}
}
}
I would have an internal ArrayList and have Store() delete the last element if its size exceeds the capacity established in the constructor. I think standard terminology, strangely enough, calls this an "LRU" list, because the least-recently-used item is what gets discarded. See wikipedia's entry for this.
You can build this up with a Collections.Generic.LinkedList<T>.
When you push an item into a full list, delete the last one and insert the new one at the front. Most operations should be in O(1) which is better than a array-based implementation.
Everyone enjoys rolling their own container classes.
But in the .NET BCL there is a little gem called SortedList<T>. You can use this to implement your MRU list or any other priority-queue type list. It uses an efficient tree structure for efficient additions.
From SortedList on MSDN:
The elements of a SortedList object
are sorted by the keys either
according to a specific IComparer
implementation specified when the
SortedList is created or according to
the IComparable implementation
provided by the keys themselves. In
either case, a SortedList does not
allow duplicate keys.
The index sequence is based on the
sort sequence. When an element is
added, it is inserted into SortedList
in the correct sort order, and the
indexing adjusts accordingly. When an
element is removed, the indexing also
adjusts accordingly. Therefore, the
index of a specific key/value pair
might change as elements are added or
removed from the SortedList object.
Operations on a SortedList object tend
to be slower than operations on a
Hashtable object because of the
sorting. However, the SortedList
offers more flexibility by allowing
access to the values either through
the associated keys or through the
indexes.
Elements in this collection can be
accessed using an integer index.
Indexes in this collection are
zero-based.
In Java, I'd use the LinkedHashMap, which is built for this sort of thing.
public class MRUList<E> implements Iterable<E> {
private final LinkedHashMap<E, Void> backing;
public MRUList() {
this(10);
}
public MRUList(final int maxSize) {
this.backing = new LinkedHashMap<E,Void>(maxSize, maxSize, true){
private final int MAX_SIZE = maxSize;
#Override
protected boolean removeEldestEntry(Map.Entry<E,Void> eldest){
return size() > MAX_SIZE;
}
};
}
public void store(E item) {
backing.put(item, null);
}
public void clear() {
backing.clear();
}
public void storeRange(E[] range) {
for (E e : range) {
backing.put(e, null);
}
}
public List<E> getList() {
return new ArrayList<E>(backing.keySet());
}
public Iterator<E> iterator() {
return backing.keySet().iterator();
}
}
However, this does iterate in exactly reverse order (i.e. LRU first, MRU last). Making it MRU-first would require basically reimplementing LinkedHashMap but inserting new elements at the front of the backing list, instead of at the end.
Java 6 added a new Collection type named Deque... for Double-ended Queue.
There's one in particular that can be given a limited capacity: LinkedBlockingDeque.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
public class DequeMruList<T> implements IMruList<T> {
private LinkedBlockingDeque<T> store;
public DequeMruList(int capacity) {
store = new LinkedBlockingDeque<T>(capacity);
}
#Override
public void Clear() {
store.clear();
}
#Override
public List<T> GetList() {
return new ArrayList<T>(store);
}
#Override
public T GetNext() {
// Get the item, but don't remove it
return store.peek();
}
#Override
public T Store(T item) {
boolean stored = false;
// Keep looping until the item is added
while (!stored) {
// Add if there's room
if (store.offerFirst(item)) {
stored = true;
} else {
// No room, remove the last item
store.removeLast();
}
}
return item;
}
#Override
public void StoreRange(T[] range) {
for (T item : range) {
Store(item);
}
}
}