获得“下一个”的最简单方法序列中的元素?

发布于 2024-12-22 14:05:25 字数 759 浏览 1 评论 0原文

我有一个 ICollection

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

那里的商品已经被预订了,所以“下一个”确实有某种意义。

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

[0] - “a”,假

[1] - “b”,正确

[2] - “c”,假

I'我试图获取 IsPreferred == true 之后的“下一个”元素。所以在上面,我想获取元素 2,并且我想清除其他 IsPreferred 值。

所以我想以此结束:

[0] - “a”,假

[1] - “b”,假

[2] - “c”,true

基本上是随机播放首选项目下降。

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

还有更好的想法吗?

I've got an ICollection<SomeClass>.

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

The items in there have been pre-ordered, so "next" does mean something.

In my scenario, the contents of the sequence looks like this:

[0] - "a", false

[1] - "b", true

[2] - "c", false

I'm trying to get the "next" element after the one that IsPreferred == true. So in the above, i want to get element 2, and i want to clear the other IsPreferred value.

So i want to end up with this:

[0] - "a", false

[1] - "b", false

[2] - "c", true

Basically shuffling the preferred item down.

What's the best way to do it? The only thing i can think of is to create a new array, add them one by one, keep track of the index of the one that is preferred, then go grab the element at the aforementioned index +1.

Any better ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

奢望 2024-12-29 14:05:25

我将使用枚举器来迭代集合 - 这就是 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 的边缘情况

I would use an enumerator to iterate over the collection - this is what foreach does behind the scenes:

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;
    }
}

This does assume that you want to stop after finding the first item with IsPreferred, and if this is the last item, still clear IsPreferred.

Edit: Fixed edge case where IsPreferred is always set to false on a collection of a single item

韶华倾负 2024-12-29 14:05:25

由于 ICollection不给你一个索引器我会选择更直接的解决方案而不是依赖 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;
    }
}

Since ICollection<T> doesn't give you an indexer I would opt for a more direct solution rather than rely on LINQ.

Assuming you want to (1) stop as soon as the condition is met, and (2) only change the value if the next item exists, this can be achieved as follows:

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;
    }
}
我要还你自由 2024-12-29 14:05:25

我只能想到一种用 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;

I can only think of a messy way doing this with LINQ:

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

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

This of course excludes error checking and is not very efficient.


Another possibility (using LINQ) would be to use Ahmad Mageed's solution (as suggested in the comments below):

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;
随风而去 2024-12-29 14:05:25

几个想法

  1. 如果您可以迭代集合,为什么我们不能在处理 i+1 之前将 i+2 值设置为 true?确保 i+2 存在
  2. 另一个想法是扩展 LinkedList 并使 current.next.next = true (如果存在)。

Couple of ideas

  1. If you can iterate over the collection why can't we set i+2 value to true before processing i+1? Be sure to make sure that i+2 exists
  2. Another idea is extending the LinkedList and make the current.next.next = true if it exists.
御弟哥哥 2024-12-29 14:05:25

既然你的集合是有序的,它可以是 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;

Since your collection is ordered, can it be an IList instead of an ICollection?

Then you could create an extension method to give you the indexes of the values where some predicate applies:

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;
    }
}

Assuming you expect only one element to ever match, it sounds like the rest would just look like this:

var preferredIndex = list.IndexWhere(x=>x.IsPreferred).Single();
list[preferredIndex].IsPreferred = false;
list[preferredIndex + 1].IsPreferred = true;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文