Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 保持序数集合的正确顺序_C#_Algorithm_Data Structures - Fatal编程技术网

C# 保持序数集合的正确顺序

C# 保持序数集合的正确顺序,c#,algorithm,data-structures,C#,Algorithm,Data Structures,我有一个简单的域对象: class FavoriteFood { public string Name; public int Ordinal; } 我希望有一个维护正确序号的域对象集合。例如,给定4种喜爱的食物: Name: Banana, Ordinal: 1 Name: Orange, Ordinal: 2 Name: Pear, Ordinal: 3 Name: Watermelon, Ordinal: 4 如果我把梨的序号改为4,西瓜的序号应该改为3 如果我添加了

我有一个简单的域对象:

class FavoriteFood
{
    public string Name;
    public int Ordinal;
 }
我希望有一个维护正确序号的域对象集合。例如,给定4种喜爱的食物:

Name: Banana, Ordinal: 1
Name: Orange, Ordinal: 2
Name: Pear, Ordinal: 3
Name: Watermelon, Ordinal: 4
如果我把梨的序号改为4,西瓜的序号应该改为3

如果我添加了一种新的最喜欢的食物(草莓),顺序是3,那么梨应该是4,西瓜应该是5

如果我把梨的序号改成2,它应该会把橙色调成3

如果我把西瓜的序号改为1,香蕉会增加到2,橘子会增加到3,梨会增加到4

实现这一目标的最佳方式是什么

更新:域对象的名称属性是动态的,并且基于用户输入。对象必须具有此Ordinal属性,因为用户可以更改其喜爱的食物的显示顺序。此序号值保存在数据库中,在填充结构时,我不能保证项目按序号顺序添加

我遇到的问题是,当底层域对象发生更改时,没有一种好的方法来更新列表中的其余项。例如:

var favoriteFoods = new List<FavoriteFood>();
var banana = new FavoriteFood { Name = "Banana", Ordinal = 1};
favoriteFoods.Add(banana);
favoriteFoods.Add(new FavoriteFood { Name = "Orange", Ordinal = 2 });
banana.Ordinal = 2;
// at this point both Banana and Orange have the same ordinal in the list. How can we make sure that Orange's ordinal gets updated too?
var-favoriteFoods=newlist();
var banana=new-FavoriteFood{Name=“banana”,序号=1};
喜欢的食物。加(香蕉);
添加(新的favoriteFoods{Name=“Orange”,序号=2});
香蕉。序数=2;
//此时,香蕉和橙色在列表中的序号相同。我们如何确保Orange的序号也得到更新?
到目前为止,我尝试了以下方法:

class FavoriteFood : INotifyPropertyChanging
{
    public string Name;
    public int Ordinal
    {
        get { return this.ordinal; }
        set
        {
            var oldValue = this.ordinal;
            if (oldValue != value && this.PropertyChanging != null)
            {
                this.PropertyChanging(new FavoriteFoodChangingObject { NewOrdinal = value, OldOrdinal = oldValue }, new PropertyChangingEventArgs("Ordinal"));
            }
            this.ordinal = value;
        }
    }

    internal struct FavoriteFoodChangingObject
    {
        internal int NewOrdinal;
        internal int OldOrdinal;
    }

    // THIS IS A TEMPORARY WORKAROUND
    internal int ordinal;

    public event PropertyChangingEventHandler PropertyChanging;
 }

 public class FavoriteFoodCollection : IEnumerable<FavoriteFood>
 {
    private class FavoriteFoodOrdinalComparer : IComparer<FavoriteFood>
    {
        public int Compare(FavoriteFood x, FavoriteFood y)
        {
            return x.Ordinal.CompareTo(y.Ordinal);
        }
    }

    private readonly SortedSet<FavoriteFood> underlyingList = new SortedSet<FavoriteFood>(new FavoriteFoodOrdinalComparer());

    public IEnumerator<FavoriteFood> GetEnumerator()
    {
        return this.underlyingList.GetEnumerator();
    }

    public void AddRange(IEnumerable<FavoriteFood> items)
    {
        foreach (var i in items)
        {
            this.underlyingList.Add(i);
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    private void UpdateOrdinalsDueToRemoving(FavoriteFood item)
    {

        foreach (var i in this.underlyingList.Where(x => x.Ordinal > item.Ordinal))
        {
            i.ordinal--;
        }
    }

    public void Remove(FavoriteFood item)
    {
        this.underlyingList.Remove(item);
        this.UpdateOrdinalsDueToRemoving(item);
    }

    public void Add(FavoriteFood item)
    {
        this.UpdateOrdinalsDueToAdding(item);
        this.underlyingList.Add(item);
        item.PropertyChanging += this.item_PropertyChanging;
    }

    private void item_PropertyChanging(object sender, PropertyChangingEventArgs e)
    {
        if (e.PropertyName.Equals("Ordinal"))
        {
            var ordinalsChanging = (FavoriteFood.FavoriteFoodChangingObject)sender;
            this.UpdateOrdinalsDueToEditing(ordinalsChanging.NewOrdinal, ordinalsChanging.OldOrdinal);
        }
    }

    private void UpdateOrdinalsDueToEditing(int newOrdinal, int oldOrdinal)
    {

        if (newOrdinal > oldOrdinal)
        {

            foreach (var i in this.underlyingList.Where(x => x.Ordinal <= newOrdinal && x.Ordinal > oldOrdinal))
            {
                //i.Ordinal = i.Ordinal - 1;
                i.ordinal--;
            }

        }
        else if (newOrdinal < oldOrdinal)
        {

            foreach (var i in this.underlyingList.Where(x => x.Ordinal >= newOrdinal && x.Ordinal < oldOrdinal))
            {
                //i.Ordinal = i.Ordinal + 1;
                i.ordinal++;
            }
        }
    }

    private void UpdateOrdinalsDueToAdding(FavoriteFood item)
    {

        foreach (var i in this.underlyingList.Where(x => x.Ordinal >= item.Ordinal))
        {
            i.ordinal++;
        }
    }
}
class FavoriteFood:InotifyPropertyChange
{
公共字符串名称;
公共整数序数
{
获取{返回this.ordinal;}
设置
{
var oldValue=this.ordinal;
if(oldValue!=value&&this.PropertyChanging!=null)
{
this.PropertyChanging(新的FavoriteFoodChangingObject{NewOrdinal=value,OldOrdinal=oldValue},新的PropertyChangingEventArgs(“Ordinal”);
}
这个。序数=值;
}
}
内部结构FavoriteFoodChangingObject
{
内部整数新序;
内部整数顺序;
}
//这是一个临时解决办法
内部整数序数;
公共事件属性更改EventHandler属性更改;
}
公共类FavoriteFoodCollection:IEnumerable
{
私有类收藏夹FoodOrdinalComparer:IComparer
{
公共整数比较(FavoriteFood x、FavoriteFood y)
{
返回x.序数比(y.序数);
}
}
private readonly SortedSet underlyingList=新建SortedSet(新建收藏夹FoodOrdinalComparer());
公共IEnumerator GetEnumerator()
{
返回此.underyingList.GetEnumerator();
}
公共无效添加范围(IEnumerable items)
{
foreach(项目中的var i)
{
本.参考列表.添加(i);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
返回此.GetEnumerator();
}
私有无效更新或取消删除(收藏夹食物项)
{
foreach(这个.underyinglist.Where中的变量i(x=>x.Ordinal>item.Ordinal))
{
i、 序数--;
}
}
公共无效删除(偏好食品项目)
{
此.underyinglist.Remove(项);
此.UpdateOrdinalsDueToRemoving(项目);
}
公共无效添加(收藏夹食品项目)
{
此更新或添加(项目);
此.参考列表.添加(项);
item.PropertyChanging+=此.item\u PropertyChanging;
}
私有无效项\u属性更改(对象发件人,属性更改事件参数e)
{
if(e.PropertyName.Equals(“序数”))
{
变量ordinalsChanging=(FavoriteFood.FavoriteFoodChangingObject)发送方;
this.updateOrdinalsDuetoEdit(ordinalsChanging.NewOrdinal,ordinalsChanging.OldOrdinal);
}
}
私有void updateOrdinalsDueToEdit(int newOrdinal,int oldOrdinal)
{
如果(新序数>旧序数)
{
foreach(在这个.underyinglist.Where(x=>x.Ordinal oldOrdinal)中的变量i)
{
//i、 序数=i.序数-1;
i、 序数--;
}
}
else if(新序数<旧序数)
{
foreach(这个.underyinglist.Where中的变量i(x=>x.Ordinal>=newOrdinal&&x.Ordinalx.Ordinal>=item.Ordinal)中的变量i)
{
i、 序数++;
}
}
}
这可以正常工作,但是使用内部序号字段是一个奇怪的解决方法。它是必需的,这样PropertyChangingEvent就不会无限地被提升。

听起来像是你想要一个新的。使用每个项目的序号作为键添加每个项目。

只需使用
列表即可:

List foods=新列表{“香蕉”、“橘子”、“梨”};
int ordinalOfOrange=食品指数(“橙色”);

如果要改变你描述的方式,“存储”那个序号不是个好主意

我会做如下事情:

public class FavoriteFoods
{
  StringComparer comparer ;
  List<string> list ;

  public FavoriteFoods()
  {
    this.list = new List<string>() ;
    this.comparer = StringComparer.InvariantCultureIgnoreCase ;
    return ;
  }

  public void Add( string food , int rank )
  {
    if ( this.list.Contains(food,comparer ) ) throw new ArgumentException("food") ;
    this.list.Insert(rank,food) ;
    return ;
  }

  public void Remove( string food )
  {
    this.list.Remove( food ) ;
    return ;
  }

  public void ChangeRank( string food , int newRank )
  {
    int currentRank = this.list.IndexOf(food) ;

    if ( currentRank < 0 ) throw new ArgumentOutOfRangeException("food") ;
    if ( newRank     <  0               ) throw new ArgumentOutOfRangeException("newRank") ;
    if ( newRank     >= this.list.Count ) throw new ArgumentOutOfRangeException("newRank") ;

    if ( newRank != currentRank )
    {
      this.Remove(food) ;
      this.Add( food , newRank ) ;
    }
    return ;
  }

  public int GetRank( string food )
  {
    int rank = this.list.IndexOf(food) ;
    if ( rank < 0 ) throw new ArgumentOutOfRangeException("food");
    return rank ;
  }

  public IEnumerable<string> InRankOrder()
  {
    foreach ( string food in this.list )
    {
      yield return food ;
    }
  }

}
公共类收藏夹食品
{
细线比较器;
名单;
公众喜爱的食物
{
this.list=新列表();
this.comparer=StringComparer.invariantCultureInogoreCase;
返回;
}
公共空添加(字符串食物,整数等级)
{
如果(this.list.Contains(food,comparer))抛出新的ArgumentException(“food”);
此列表。插入(等级、食物);
返回;
}
公共空间移除(串食物)
{
这个。列表。移除(食物);
返回;
}
公共空变秩(字符串食物,int newRank)
{
int currentRank=this.list.IndexOf(食物);
如果(currentRank<0)抛出新参数
public class FavoriteFoods
{
  StringComparer comparer ;
  List<string> list ;

  public FavoriteFoods()
  {
    this.list = new List<string>() ;
    this.comparer = StringComparer.InvariantCultureIgnoreCase ;
    return ;
  }

  public void Add( string food , int rank )
  {
    if ( this.list.Contains(food,comparer ) ) throw new ArgumentException("food") ;
    this.list.Insert(rank,food) ;
    return ;
  }

  public void Remove( string food )
  {
    this.list.Remove( food ) ;
    return ;
  }

  public void ChangeRank( string food , int newRank )
  {
    int currentRank = this.list.IndexOf(food) ;

    if ( currentRank < 0 ) throw new ArgumentOutOfRangeException("food") ;
    if ( newRank     <  0               ) throw new ArgumentOutOfRangeException("newRank") ;
    if ( newRank     >= this.list.Count ) throw new ArgumentOutOfRangeException("newRank") ;

    if ( newRank != currentRank )
    {
      this.Remove(food) ;
      this.Add( food , newRank ) ;
    }
    return ;
  }

  public int GetRank( string food )
  {
    int rank = this.list.IndexOf(food) ;
    if ( rank < 0 ) throw new ArgumentOutOfRangeException("food");
    return rank ;
  }

  public IEnumerable<string> InRankOrder()
  {
    foreach ( string food in this.list )
    {
      yield return food ;
    }
  }

}