List<> 获取下一个元素或获取第一个
Posted
技术标签:
【中文标题】List<> 获取下一个元素或获取第一个【英文标题】:List<> Get Next element or get the first 【发布时间】:2009-04-22 11:20:59 【问题描述】:我想获取列表中的下一个元素,如果列表在其末尾,我想要第一个元素。 换句话说,我只想让它循环。
List<int> agents = taskdal.GetOfficeAgents(Branches.aarhusBranch);
if (lastAgentIDAarhus != -1)
int index = agents.IndexOf(lastAgentIDAarhus);
if (agents.Count > index + 1)
lastAgentIDAarhus = agents[index + 1];
else
lastAgentIDAarhus = agents[0];
else
lastAgentIDAarhus = agents[0];
我对上面显示的我自己的解决方案相当不满意,如果你有更好的解决方案,请告诉我:)
【问题讨论】:
【参考方案1】:lastAgentIDAarhus = agents[index == -1 ? 0 : index % agents.Count];
MOD 运算符 % 的使用自动将索引切分到可能索引的范围内。
模运算符是对 DIV (/) 运算符的补充,它返回两个整数相除的余数。例如,如果您将 9 除以 6,则结果为 1,余数为 3。MOD 运算符要求 3。
【讨论】:
哇,如果可行的话,这是一个非常简洁的解决方案:) 愿意解释一下吗? mod 运算符进行模运算,这正是您想要的。如果您可以将索引初始化为 0 而不是 -1,您可以使用:lastAgentIDAarhus = agent[index % (agents.Count - 1)] 我觉得应该是index % ( agents.Count )
@EricYin:您的 Count 将始终比您拥有的最高索引高 1。这是因为(通常)索引从 0 开始,而 Count 属性从 1 开始。
@EricYin 是正确的。假设您有一个包含 10 个项目的列表,并且您尝试访问索引 10 处的项目(它不存在)。 10%10=0 是你想要的,而不是 10%9=1。【参考方案2】:
或者简单地说:
public static T NextOf<T>(this IList<T> list, T item)
var indexOf = list.IndexOf(item);
return list[indexOf == list.Count - 1 ? 0 : indexOf + 1];
例子:
List<string> names = new List<string>();
names.Add("jonh");
names.Add("mary");
string name = String.Empty;
name = names.NextOf(null); //name == jonh
name = names.NextOf("jonh"); //name == mary
name = names.NextOf("mary"); //name == jonh
【讨论】:
【参考方案3】:作为对此略有不同的看法,这里有一个扩展方法,您可以使用它来使任何 IEnumerable '循环'
public static IEnumerable<T> AsCircularEnumerable<T>(this IEnumerable<T> enumerable)
var enumerator = enumerable.GetEnumerator();
if(!enumerator.MoveNext())
yield break;
while (true)
yield return enumerator.Current;
if(!enumerator.MoveNext())
enumerator = enumerable.GetEnumerator();
所以你可以像这样使用它
var agents = new List<int> 1, 2, 3, 4, 123, 234, 345, 546;
foreach(var i in agents.AsCircularEnumerable())
Console.WriteLine(i);
这将继续进行...... :)
【讨论】:
如果列表中有 3 个元素,并且如果我使用 4 或 5 的索引值 - 获取列表中的项目 - 我会得到列表的第一个和第二个元素吗? 我不确定你的意思。如果您询问使用我上面概述的解决方案进行索引,因为这不是一个列表,它是一个 IEnumerable,并且您不能在 IEnumerable 上使用索引器,那么不,您不会。您可以改用agents.AsCircularEnumerable().Skip(10).First() 之类的东西。【参考方案4】:我喜欢Vinicius's idea 使用扩展方法。不幸的是,他发布的代码会引发异常。这是基于他的,但它不会抛出异常并且非常简单易读(恕我直言):
public static T Next<T>(this IList<T> list, T item)
var nextIndex = list.IndexOf(item) + 1;
if (nextIndex == list.Count)
return list[0];
return list[nextIndex];
如果传入的项不在列表中,它将返回列表中的第一项,因为list.IndexOf(item)
在这种情况下将返回-1
;
【讨论】:
Koveras,哪里会引发异常? 记住 list.IndexOf(item) 将返回 -1 如果没有找到项目。 这对于扩展来说确实是个好主意。我对其进行了一些修改并实现了它:)【参考方案5】:差别不大,但至少少了一些代码(至少在编辑器中);o)
List<int> agents = taskdal.GetOfficeAgents(Branches.aarhusBranch);
if (lastAgentIDAarhus != -1)
int index = agents.IndexOf(lastAgentIDAarhus);
lastAgentIDAarhus = (agents.Count > index + 1 ? agents[index + 1] : agents[0]);
else
lastAgentIDAarhus = agents[0];
【讨论】:
【参考方案6】:如果我们添加一些检查来避免常见错误,您怎么看?
public static class ListExtensions
public static TType Next<TType>(this IList<TType> list, TType item)
if (list == null) return default(TType);
var itemIndex = list.IndexOf(item);
if (itemIndex < 0) return list.FirstOrDefault();
var nextIndex = itemIndex + 1;
return nextIndex >= list.Count
? list.FirstOrDefault()
: list[nextIndex];
【讨论】:
【参考方案7】:字符串 line = lines[lines.FindIndex(x => x.Contains(item)) + 1];
【讨论】:
以上是关于List<> 获取下一个元素或获取第一个的主要内容,如果未能解决你的问题,请参考以下文章