如何在自定义集合(c#)上实现删除方法?

时间:2017-02-12 15:14:02

标签: c# arrays generics collections

我已经完成了一项简单(或没有)任务,我想知道如何以最灵活的方式实现实施。 所以,假设我给出了一个接口

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,那么我的实现将不会覆盖它。

任何想法或建议将不胜感激 谢谢

3 个答案:

答案 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)

附加说明:这只找到具有“最大”值的第一个元素。如果有多个人拥有该最大值,您没有指定会发生什么。你可能想添加一些参数检查。