我已经完成了一项简单(或没有)任务,我想知道如何以最灵活的方式实现实施。 所以,假设我给出了一个接口
public interface IPerson
{
int GetId();
string GetFirstName();
string GetLastName();
DateTime GetDateOfBirth();
int GetHeight();
//More methods can be added later...
}
简而言之,可能会添加许多可以定义对象Person的属性。 我被要求实现名为" PersonCollection"的自定义集合。遵守以下规则: 1)它应该使用"添加方法" - 添加作为输入给出的person对象。 2)(这是最棘手的部分)删除 - 删除具有最大值的人物对象并返回它。现在,一个人具有最大价值意味着什么? 可能有许多可能的"算法"确定例如以名字/ 姓氏/身高/或将添加的此界面的任何新属性 未来;您事先不知道可能适用的算法和哪些算法 应该使用一个。因此,实施必须如此灵活 可以通过支持所有潜在的算法。例如:如果是开发人员 Person接口以某种方式更改其属性,然后这仍然不应该 以任何方式影响您对PersonCollection的实现! 那么,我怎样才能制作一个"泛型"找到任何给定属性的最大值的方法?它甚至可能吗?
这是我实施课程的开始:
public class PersonCollection : IEnumerable<IPerson>
{
private PersonCollection _pCollection;
public PersonCollection(PersonCollection pCollection)
{
_pCollection = pCollection;
}
public async Task Add(IPerson person)
{
await _pCollection.Add(person);
}
public IEnumerator<IPerson> GetEnumerator()
{
return _pCollection.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
起初我想过使用Linq查询,但是每个查询只能使用lambda访问一个属性,所以如果有人将属性添加到IPerson,那么我的实现将不会覆盖它。
任何想法或建议将不胜感激 谢谢
答案 0 :(得分:3)
那么,我如何制作一种“通用”方法来查找任何给定属性的最大值?
让我们首先注意到这是您之前要求的更受限制的版本:
通过支持所有可能的算法,实现必须尽可能灵活。
你知道为什么那些不同吗?假设我想要的最大算法是“姓氏最长的人,但如果有领带,那么名字最短的人,如果有领带,那么最重的人。”这不是找到特定属性的最大值的算法。它在整个集合中最大化一个值,然后在一个子集上最小化另一个值,依此类推。
现在,您应该意识到您的任务危险地未明确。 如果最大值为零或者最大值为两个或更多,则没有说明该怎么做。如果有领带怎么办?如果收集是空的怎么办?对于这些场景中发生的事情,您需要有精确规则。
该指配以另一种方式指定。你说“所有潜在的算法”,但究竟是什么的所有潜在算法?在这里,我想到了一个潜在算法的想法,Wendys比McDonalds好,McDonalds比汉堡王好,汉堡王比Wendys好,Red Lobster比所有这些都好,而且我能够确定Red Lobster是赢家。您的算法是否需要处理不及物敏感度量?这不是学术观点; C#中的重载决策算法需要能够解决这个最大化问题。 (当我为C#团队试用时,这实际上是我的面试问题之一!好时光。)
为了让它变得更容易,让我们清醒一点。我们希望找到一个集合的最大值,给出一个产生总订单的比较运算符。
现在回答你的实际问题:
起初我想过使用Linq查询,但每个查询只能使用lambda访问一个属性,
说谁?什么阻止你访问lambda中的多个属性?
你遇到过这个解决方案。 LINQ还需要能够对集合执行任意操作,并且通过接受lambda来实现。
什么是lambda?
您希望找到一组的最大值。所以请一个带两个人的代表,告诉你哪个更大。我建议Comparison<T>
。
https://msdn.microsoft.com/en-us/library/tfakywbh(v=vs.110).aspx
然后实现标准最大化算法:假设第一个是最大值,在你找到一个更大的列表之前运行你的列表,继续运行直到找到最大值。
答案 1 :(得分:1)
尝试一种功能性方法......
public IPerson RemoveMax(Func<IEnumerable<IPerson>, IPerson> maxFunction)
{
IPerson person = maxFunction(this);
Remove(person);
return maxFunction(this);
}
public void Remove(IPerson person)
{
//Person removal code...
}
然后你可以将你需要的任何函数传递给RemoveMax以便找到最大的人,只要该函数将IEnumerable作为参数并返回一个IPerson。 您可以根据具体情况编写许多不同的maxFunction。示例maxFunction的定义类似于......
public IPerson MaxPerson(IEnumerable<IPerson> personCollection)
{
IPerson maxPerson;
foreach(IPerson person in personCollection)
//Whatever to find max person based on properties...
return maxPerson;
}
答案 2 :(得分:0)
我建议在内部使用IList<IPerson>
并根据您的需要实施ICollection<IPerson>
或public PersonCollection : IList<Person> // or ICollection<IPerson>
{
private readonly List<IPerson> innerList = new List<IPerson>();
// example implementation of IList.Add
public void Add (IPerson person)
{
innerList.Add(person);
}
// implement the other interface methods accordingly
// extend functionality with your methods
public async Task AddAsync(IPerson person) // note async naming convention
{
// your async add implementaion
}
}
。这些接口的实现可以是直接转发到内部列表的调用:
RemoveByMaxOf
现在我建议使用// as instance method of PersonCollection
public Person RemoveByMaxOf<T>(Func<IPerson, T> propertySelector) where T : IComparable
{
if (Count == 0) return null;
IPerson found = innerList0];
T max = propertySelector(found);
foreach (Person person in innerList.Skip(1))
{
T current = propertySelector(person);
if (current.CompareTo(max) <= 0) continue;
found = person;
max = current;
}
innerList.Remove(found);
return found;
}
方法:
IPerson
所以这需要一个“选择器”:一个委托,它将IComparable
投射到你想要比较的属性的值。
为了能够找到最大值,属性类型必须实现PersonCollection persons = ... // get your persons
IPerson removed = persons.RemoveByMaxOf(person => person.Name);
。无法比较通用对象。
您可以这样称呼:
Name
您可以扩展该方法以获取自定义比较器。这样,类的用户可以决定“最大”的真正含义(例如Name
的字母最大值或public Person RemoveByMaxOf<T>(Func<IPerson, T> propertySelector, Func<T, T, int> comparer)
{
if (Count == 0) return null;
IPerson found = innerList0];
T max = propertySelector(found);
foreach (Person person in innerList.Skip(1))
{
T current = propertySelector(person);
// use custom comparer
if (comparer(current, max) <= 0) continue;
found = person;
max = current;
}
innerList.Remove(found);
return found;
}
的长度):
IPerson removed = persons.RemoveByMaxOf(
person => person.Name,
(name1, name2) => name1.Length.CompareTo(name2.Length));
现在你可以这样称呼它:
setTimeout(() => localStorage.getItem('profile'), 1000)
附加说明:这只找到具有“最大”值的第一个元素。如果有多个人拥有该最大值,您没有指定会发生什么。你可能想添加一些参数检查。