3

我有一个ICollection<SomeClass>.

public class SomeClass
{
   public string Text { get; set; }
   public bool IsPreferred { get; set; }
}

那里的物品已经预订,所以“下一个”确实意味着什么。

在我的场景中,序列的内容如下所示:

[0] - “一”,假

[1] - “b”,真

[2] - “c”,假

我试图在那个之后获得“下一个”元素IsPreferred == true。所以在上面,我想得到元素 2,我想清除另一个IsPreferred值。

所以我想结束这个:

[0] - “一”,假

[1] - “b”,假的

[2] - “c”,真

基本上将首选项目洗牌。

最好的方法是什么?我唯一能想到的就是创建一个新数组,将它们一一添加,跟踪首选数组的索引,然后在上述索引 +1 处获取元素。

有更好的想法吗?

4

5 回答 5

5

我会使用枚举器来遍历集合 - 这是 foreach 在幕后所做的:

var enumerator = collection.GetEnumerator();

while (enumerator.MoveNext())
{
    if (enumerator.Current.IsPreferred)
    {
        var oldPreferred = enumerator.Current;

        if (enumerator.MoveNext())
        {
            oldPreferred.IsPreferred = false;
            enumerator.Current.IsPreferred = true;
        }

        break;
    }
}

这确实假设您想在找到第一个带有 IsPreferred 的项目后停止,如果这是最后一个项目,仍然清除 IsPreferred。

编辑:固定边缘情况,其中 IsPreferred 在单个项目的集合上始终设置为 false

于 2011-12-21T01:00:01.717 回答
4

由于ICollection<T>没有给你一个索引器,我会选择更直接的解决方案,而不是依赖 LINQ。

假设您希望(1)在满足条件时立即停止,并且(2)仅在存在下一项时才更改值,这可以通过以下方式实现:

bool isFound = false;
SomeClass targetItem = null;
foreach (var item in list)
{
    if (isFound)
    {
        item.IsPreferred = true;
        targetItem.IsPreferred = false;
        break;
    }
    if (item.IsPreferred)
    {
        targetItem = item;
        isFound = true;
    }
}
于 2011-12-21T01:10:43.173 回答
3

我只能想到用 LINQ 做这件事的一种混乱方式:

var x = collection.SkipWhile(z => !z.IsPreferred);
SomeClass a = x.First();
SomeClass b = x.Skip(1).First();

a.IsPreferred = false;
b.IsPreferred = true;

这当然排除了错误检查并且效率不高。


另一种可能性(使用 LINQ)是使用 Ahmad Mageed 的解决方案(如以下评论中所建议):

var x = collection.SkipWhile(z => !z.IsPreferred);
SomeClass a = x.FirstOrDefault();
SomeClass b = x.ElementAtOrDefault(1);

if (a != null) a.IsPreferred = false;
if (b != null) b.IsPreferred = true;
于 2011-12-21T00:52:19.350 回答
0

几个想法

  1. 如果您可以遍历集合,为什么我们不能在处理 i+1 之前将 i+2 值设置为 true?一定要确保 i+2 存在
  2. 另一个想法是扩展LinkedList并使 current.next.next = true 如果存在。
于 2011-12-21T00:58:45.660 回答
0

由于您的集合是有序的,它可以是 IList 而不是 ICollection 吗?

然后,您可以创建一个扩展方法,为您提供某些谓词适用的值的索引:

static IEnumerable<int> IndexWhere<T>(this IList<T> list, 
                                      Func<T, bool> predicate)
{
    for(int i = 0; i < list.Count; i++)
    {
        if(predicate(list[i])) yield return i;
    }
}

假设您希望只有一个元素匹配,听起来其余的看起来像这样:

var preferredIndex = list.IndexWhere(x=>x.IsPreferred).Single();
list[preferredIndex].IsPreferred = false;
list[preferredIndex + 1].IsPreferred = true;
于 2011-12-21T00:59:09.207 回答