使用 SortedDictionary TakeWhile 返回空

发布于 2024-10-17 01:00:08 字数 1267 浏览 10 评论 0原文

TakeWhile 扩展方法的工具提示中有以下注释:“元素的索引用于谓词函数的逻辑”。请注意,此工具提示在普通工具提示中不可见,而仅在变量 sortedDictionary 的列表成员的智能感知列表的工具提示中可见。

这正是与 SortedDictionary 结合使用所需要的。

var first = sortedDictionary.First(kv => kv.Key.ToString().StartsWith(searchkey));
var last= sortedDictionary.Last(kv => kv.Key.ToString().StartsWith(searchkey));
var range = sortedDictionary.TakeWhile(kv => kv.Key.ToString().StartsWith(searchkey));

第一个和最后一个项目已找到并且正确,但是我的收藏范围是空的。
这里有什么问题吗?我期望一个范围包含第一个和最后一个之间的所有项目,包括它们。

我仍然可以使用第一个和最后一个找到范围,但 TakeWhile 使用索引,而 FirstLast 显然不使用索引。

编辑:“使用索引”结果与排序无关,但您可以在查询中使用索引。例如,当我用 SortedList 替换 SortedDictionary 时,我可以这样做:

int ix1 = sortedList.IndexOfKey(first.Key);
int ix2 = sortedList.IndexOfKey(last.Key);
var range = sortedList.SkipWhile((x, i) => i < ix1).TakeWhile((x, i) => i <= ix2);

同样使用 SortedDictionary 我可以这样做:

var range = sortedList.SkipWhile(x => !x.Key.ToString().StartsWith(searchkey))
                      .TakeWhile(x => x.Key.ToString().StartsWith(searchkey));

我必须测试哪种方法更快,而且必须测试Where 查询。

The TakeWhile extension method has the following comment in its tooltip: "the element's index is used in the logic of the predicate function". Note that this tooltip is not visible in the normal tooltip but only in the tooltip of the list of intellisense for the lists members of the variable sortedDictionary.

That's exactly what is was looking for in combination with a SortedDictionary.

var first = sortedDictionary.First(kv => kv.Key.ToString().StartsWith(searchkey));
var last= sortedDictionary.Last(kv => kv.Key.ToString().StartsWith(searchkey));
var range = sortedDictionary.TakeWhile(kv => kv.Key.ToString().StartsWith(searchkey));

The items first and last are found and correct, however my collection range is empty.
What is wrong here? I expected a range with all items between first and last including them.

I could still find the range using first and last but TakeWhile uses the index while First and Last apparantly don't.

EDIT: "using the index" turns out to have nothing to do with sorting but you can use the index in the query. E.g. when I replace SortedDictionary with SortedList I can do:

int ix1 = sortedList.IndexOfKey(first.Key);
int ix2 = sortedList.IndexOfKey(last.Key);
var range = sortedList.SkipWhile((x, i) => i < ix1).TakeWhile((x, i) => i <= ix2);

Also with SortedDictionary I can do:

var range = sortedList.SkipWhile(x => !x.Key.ToString().StartsWith(searchkey))
                      .TakeWhile(x => x.Key.ToString().StartsWith(searchkey));

I will have to test which method is faster and also have to test the Where query.

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

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

发布评论

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

评论(3

不美如何 2024-10-24 01:00:08

如果序列中的第一个元素与谓词不匹配,则 TakeWhile 方法将退出:

从序列中返回元素
只要指定条件为真

First 方法将采用第一个与您的谓词匹配的元素:

返回a中的第一个元素
满足指定的序列
情况

与第一种方法相反,最后 方法将采用最后一个方法与您的谓词匹配的元素:

返回序列的最后一个元素
满足指定条件

我猜测 TakeWhile 会提前退出,因为迭代开始时它们没有与条件匹配的元素。

如果您想要示例中第一个和最后一个元素之间的元素范围(包括第一个和最后一个项目),请尝试以下操作:

var range = sortedDictionary.SkipWhile( x => !x.Equals( first ) )
  .TakeWhile( x => !x.Equals( last ) )
  .Concat( new SortedDictionary<string, string> { { last.Key, last.Value } } );

或者您可以像我一样不要过度思考,并使用更简单的方法,使用 Where 方法如 Jeff 的示例

If the first element in your sequence does not match your predicate, then the TakeWhile method will exit:

Returns elements from a sequence as
long as a specified condition is true

The First method will take the first element that matches your predicate:

Returns the first element in a
sequence that satisfies a specified
condition

Opposite of the First method, the Last method will take the last element that matches your predicate:

Returns the last element of a sequence
that satisfies a specified condition

I'm guessing that the TakeWhile is exiting early because their are no elements matching the condition when the iteration begins.

If you want the range of elements between the first and last element from your example (including both the first and last item), then try this:

var range = sortedDictionary.SkipWhile( x => !x.Equals( first ) )
  .TakeWhile( x => !x.Equals( last ) )
  .Concat( new SortedDictionary<string, string> { { last.Key, last.Value } } );

Or you could just not over-think this like me and use a simpler approach using the Where method as in Jeff's example.

毁虫ゝ 2024-10-24 01:00:08

TakeWhile() 将从序列开头开始获取项目,只要它们都满足谓词即可。如果第一项未通过谓词,则结果为空。您正在讨论的描述来自 重载,其中包含索引 (你没有使用)。

只需正常过滤项目,它应该会产生您期望的范围(由于排序)。

var range = sortedDictionary.Where(kv => kv.Key.ToString().StartsWith(searchkey));

TakeWhile() will take items starting from the beginning of the sequence as long as they all satisfy the predicate. If the first item fails the predicate, the result is empty. The description you are talking about is from the overload that includes an index (which you aren't using).

Just filter items normally and it should yield the range you are expecting (due to the sorting).

var range = sortedDictionary.Where(kv => kv.Key.ToString().StartsWith(searchkey));
烟花肆意 2024-10-24 01:00:08

您阅读的工具提示适用于其谓词具有 Int32 作为参数的重载 MSDN 链接

您介意发布一些代码来看看为什么它返回空范围吗?以下代码按预期工作(我复制/粘贴了您的代码)。

        var sortedDictionary = new SortedDictionary<string, string>();
        var searchkey = "test";
        sortedDictionary.Add("test1", "value");
        sortedDictionary.Add("test2", "value");
        sortedDictionary.Add("test3", "value");
        sortedDictionary.Add("test4", "value");

        var first = sortedDictionary.First(kv => kv.Key.ToString().StartsWith(searchkey));
        var last = sortedDictionary.Last(kv => kv.Key.ToString().StartsWith(searchkey));
        var range = sortedDictionary.TakeWhile(
            kv => kv.Key.ToString().StartsWith(searchkey));
        foreach (var c in range)
        {
            Console.WriteLine(c);
        }
        Console.ReadKey();

The tooltip you read is for an overload whose predicate has a Int32 as a parameter MSDN Link

Would you mind posting some code as to see why it's returning an empty range?. The following code works as expected (I copy/pasted your code).

        var sortedDictionary = new SortedDictionary<string, string>();
        var searchkey = "test";
        sortedDictionary.Add("test1", "value");
        sortedDictionary.Add("test2", "value");
        sortedDictionary.Add("test3", "value");
        sortedDictionary.Add("test4", "value");

        var first = sortedDictionary.First(kv => kv.Key.ToString().StartsWith(searchkey));
        var last = sortedDictionary.Last(kv => kv.Key.ToString().StartsWith(searchkey));
        var range = sortedDictionary.TakeWhile(
            kv => kv.Key.ToString().StartsWith(searchkey));
        foreach (var c in range)
        {
            Console.WriteLine(c);
        }
        Console.ReadKey();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文