C# 是否有更好的方法返回列表中的下一项并从末尾循环到前面?

C# 是否有更好的方法返回列表中的下一项并从末尾循环到前面?,c#,linq,list,enumeration,C#,Linq,List,Enumeration,我有以下不同字符串的列表: “A” “B” “C” 如果我想要A之后的项目,我得到B。B之后,我得到C。C之后,我得到A。目前我有以下代码,但出于某种原因,我觉得有更好的方法来实现这一点(也许?) 私有字符串GetNext(IList项,字符串curr) { if(String.IsNullOrWhitespace(curr)) 退货项目[0]; var指数=项目指数(货币); 如果(索引==-1) 退货项目[0]; return(index+1==items.Count)?items[0]:i

我有以下不同字符串的列表:

“A”
“B”
“C”

如果我想要A之后的项目,我得到B。B之后,我得到C。C之后,我得到A。目前我有以下代码,但出于某种原因,我觉得有更好的方法来实现这一点(也许?)

私有字符串GetNext(IList项,字符串curr)
{
if(String.IsNullOrWhitespace(curr))
退货项目[0];
var指数=项目指数(货币);
如果(索引==-1)
退货项目[0];
return(index+1==items.Count)?items[0]:items[index+1];
}

我当然也愿意采用林克式的方式来做这件事:)

我想也许你可以改变路线

return (index + 1 == items.Count) ? items[0] : items[index + 1];
比如

return items[(index + 1) % items.Count];

您可以使用mod运算符将其简化一点,并将所有内容合并到一条语句中:

return items[((String.IsNullOrWhitespace(curr) 
                ? 0 
                : items.IndexOf(curr)) + 1) % items.Count]

它肯定更短,但我不确定它是否更可读:)

如果跟踪当前索引而不是当前字符串,我可以看到一些优化,但要做到这一点,项目列表必须是固定的,即不更改

您还可以
返回项目[(索引+1)%items.Count]


否则,该代码在我看来很好,但可能有人有更聪明的解决方案。

您的解决方案在功能上是正确的,但其性能还有一点不尽如人意。通常,在处理列表式结构时,您会期望
GetNext
将在O(1)时间内返回结果,但此解决方案是O(N)


LINQ在这里不是合适的工具

听起来a是这里最好的收藏:

var linkedItems = new LinkedList<String>(items);
LinkedListNode current = linkedItems.Find("C");
String afterC = current.Next == null ? linkedItems.First.Value : current.Next.Value;
var linkedItems=新的LinkedList(项目);
LinkedListNode当前=linkedItems.Find(“C”);
字符串afterC=current.Next==null?linkedItems.First.Value:current.Next.Value;

与列表相比,LinkedList的优点和缺点是什么。

我认为最好的解决方案是在下面的链接中,我尝试了一下,效果很好

一种灵巧的方式:

var result = (from str in list
              let index = list.IndexOf(curr) + 1
              select list.ElementAtOrDefault(index) ?? list[0]).First();

我想这就是你想要的for@hyp:嗯,如果传入的参数是
循环链接列表
,这将起作用,但它只是一个
IList
。这是一个很好的改进,我接受它。虽然它应该是(index+1)对吗?我不这么认为,因为在数组Count=3中,当你得到index=3时,它将返回3%3==0。当您得到index=2(返回'C')时,您将得到正确的结果2%3=2异常索引是零基的,因此我永远不会为第三项得到3,而是得到2。第一项将返回0。另外,作为奖励,我可以删除
if(index==-1)
复选框,因为
(-1+1)%Anything
始终为零。是的。只是要提到:这对空列表和空引用都不安全,但原始实现也不安全。@eFloh:是的,我没有提到检查空列表或空列表的部分,这应该会引发异常。我只是还没有添加我的异常处理(契约)。这是一个非常有趣的方法。比我想象的要复杂一点,但肯定很有趣。另外,仅供参考。我不接受这个答案的唯一原因是因为函数接受了一个
IList
,我不想为每个函数调用创建一个新的迭代器。
IList<string> list = ...;
var iterator = WrappingIterator<string>.CreateAt(list, "B");
Console.WriteLine(iterator.GetNext());  // Prints C
Console.WriteLine(iterator.GetNext());  // Prints A
Console.WriteLine(iterator.GetNext());  // Prints B
var linkedItems = new LinkedList<String>(items);
LinkedListNode current = linkedItems.Find("C");
String afterC = current.Next == null ? linkedItems.First.Value : current.Next.Value;
var result = (from str in list
              let index = list.IndexOf(curr) + 1
              select list.ElementAtOrDefault(index) ?? list[0]).First();