8

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

“A”
“B”
“C”

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

private string GetNext(IList<string> items, string curr)
{
    if (String.IsNullOrWhitespace(curr))
        return items[0];

    var index = items.IndexOf(curr);
    if (index == -1)
        return items[0];

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

我也绝对愿意采用 LINQ 式的方式来做这件事 :)

4

7 回答 7

7

您拥有的解决方案在功能上是正确的,但它的性能还有一些不足之处。通常在处理列表样式结构时,您会期望GetNext在 O(1) 时间内返回结果,但此解决方案是 O(N)。

public sealed class WrappingIterator<T> {
  private IList<T> _list;
  private int _index;
  public WrappingIterator<T>(IList<T> list, int index) {
    _list = list;
    _index = index;
  }
  public T GetNext() {
    _index++;
    if (_index == _list.Count) {
      _index = 0;
    }
    return _list[_index];
  }

  public static WrappingIterator<T> CreateAt(IList<T> list, T value) {
    var index = list.IndexOf(value);
    return new WrappingIterator(list, index);
  }
}

这里的初始调用CreateAt是 O(N),但后续调用GetNext是 O(1)。

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
于 2012-04-23T15:46:09.690 回答
6

我想也许你可以换行

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

对于类似的东西

return items[(index + 1) % items.Count];
于 2012-04-23T15:40:45.753 回答
1

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

你也可以return items[(index + 1) % items.Count];

否则,该代码对我来说看起来不错,但也许有人有更聪明的解决方案。

于 2012-04-23T15:42:59.797 回答
1

LINQ 在这里不是合适的工具。

听起来好像 aLinkedList<T>会是更好的集合:

var linkedItems = new LinkedList<String>(items);
LinkedListNode current = linkedItems.Find("C");
String afterC = current.Next == null ? linkedItems.First.Value : current.Next.Value;

以下是 LinkedList 与 List 相比的优缺点。

于 2012-04-23T15:49:26.623 回答
1

一种linq方式:

var result = (from str in list
              let index = list.IndexOf(curr) + 1
              select list.ElementAtOrDefault(index) ?? list[0]).First();
于 2012-04-23T15:53:02.227 回答
0

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

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

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

于 2012-04-23T15:42:05.250 回答
0

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

http://www.dotnetperls.com/sort-list

于 2012-04-23T15:52:58.080 回答