Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 什么';这是实现';拆分';基于条件的通用列表?_C#_Linq_Performance - Fatal编程技术网

C# 什么';这是实现';拆分';基于条件的通用列表?

C# 什么';这是实现';拆分';基于条件的通用列表?,c#,linq,performance,C#,Linq,Performance,(高度简化的示例) 我有一个字符串的通用列表: var strings = new List<string> { "abc", "owla", "paula", "lala", "hop" }; var strings=新列表{“abc”、“owla”、“paula”、“lala”、“hop”}; 我正在寻找一种最有效的方法,将这个列表拆分为一个包含满足条件的元素的列表和一个不满足相同条件的元素的列表 Func<string, bool> condition = s

(高度简化的示例) 我有一个字符串的通用列表:

var strings = new List<string> { "abc", "owla", "paula", "lala", "hop" };
var strings=新列表{“abc”、“owla”、“paula”、“lala”、“hop”};
我正在寻找一种最有效的方法,将这个列表拆分为一个包含满足条件的元素的列表和一个不满足相同条件的元素的列表

Func<string, bool> condition = s => s.IndexOf("o") > -1;
Predicate<string> kickOut = s => s.IndexOf("o") > -1;
var stringsThatMeetCondition = strings.Where(condition);
strings.RemoveAll(kickOut);
var stringsThatDontMeetCondition = strings;
Func condition=s=>s.IndexOf(“o”)>-1;
谓词限位=s=>s.IndexOf(“o”)>-1;
var stringsThatMeetCondition=strings.Where(条件);
字符串。移除所有(限位);
var stringsthattmentmeetcondition=字符串;
有没有办法只在原始列表中循环一次?

使用一些linq:

var matches = list.Select(s => s.IndexOf("o") > -1).ToList();
var notMatches = list.Except(matches).ToList();
list.Clear();
list.AddRange(matches);
更新:如评论中所述,请小心更改列表,因为linq方法尝试按需更改,在您开始查看
IEnumerable
之前,它们不会迭代列表。但是,在我的例子中,我调用了
ToList
,这将有效地使它在整个项目列表中运行。

使用一些linq:

var matches = list.Select(s => s.IndexOf("o") > -1).ToList();
var notMatches = list.Except(matches).ToList();
list.Clear();
list.AddRange(matches);
更新:如评论中所述,请小心更改列表,因为linq方法尝试按需更改,在您开始查看
IEnumerable
之前,它们不会迭代列表。然而,在我的例子中,我调用
ToList
,这将有效地使它在整个项目列表中运行。

这样做:

IEnumerable<T> FilterAndRemove(this List<T> list, Func<T, bool> pred)
{
  List<T> filtered = new List<T>();
  int i = 0;
  while(i < list.Count)
  {
     if (pred(list[i]))
     {
        filtered.Add(list[i]);
        list.RemoveAt(i);
     }
     else
     { 
        ++i;
     }
  }
  return list;
}
IEnumerable FilterAndRemove(此列表,Func pred)
{
列表过滤=新列表();
int i=0;
而(i
但我相信你已经想到了类似的事情。你能以你所追求的效率更新你的答案吗

请注意,使用
pred
运行两次筛选!原始列表上的pred仍然是O(n),一点效率都没有。特别是考虑到对于这两个结果集,您将获得惰性评估的全部好处。另见Rob的答案

这个算法在O(n^2)中

除了删除每个元素,您还可以将它们收集到一个新列表中,并在返回之前将它们复制到输入列表中。这也会让你得到O(n)

O(n)的另一个选项是切换到链表。

这样做:

IEnumerable<T> FilterAndRemove(this List<T> list, Func<T, bool> pred)
{
  List<T> filtered = new List<T>();
  int i = 0;
  while(i < list.Count)
  {
     if (pred(list[i]))
     {
        filtered.Add(list[i]);
        list.RemoveAt(i);
     }
     else
     { 
        ++i;
     }
  }
  return list;
}
IEnumerable FilterAndRemove(此列表,Func pred)
{
列表过滤=新列表();
int i=0;
而(i
但我相信你已经想到了类似的事情。你能以你所追求的效率更新你的答案吗

请注意,使用
pred
运行两次筛选!原始列表上的pred仍然是O(n),一点效率都没有。特别是考虑到对于这两个结果集,您将获得惰性评估的全部好处。另见Rob的答案

这个算法在O(n^2)中

除了删除每个元素,您还可以将它们收集到一个新列表中,并在返回之前将它们复制到输入列表中。这也会让你得到O(n)

O(n)的另一个选项是切换到链表。

为什么不直接使用

var stringsThatMeetCondition = strings.Where(condition);
var stringsThatDontMeetCondition = strings.Where(x => !condition(x));
当然,最终会将条件应用于列表中的每个元素两次。为了避免这种情况,您可能需要编写一个通用的拆分函数,它不会那么整洁。

为什么不直接使用它呢

var stringsThatMeetCondition = strings.Where(condition);
var stringsThatDontMeetCondition = strings.Where(x => !condition(x));
Func<string, bool> condition = ...;
var groupedStrings = strings.GroupBy(condition)
var stringsMeetingCondition = groupedStrings.FirstOrDefault(g => g.Key);
var stringsNotMeetingCondition = groupedStrings.FirstOrDefault(g => !g.Key);
当然,最终会将条件应用于列表中的每个元素两次。为了避免这种情况,您可能需要编写一个通用的拆分函数,它不会那么整洁。

Func condition=。。。;
Func<string, bool> condition = ...;
var groupedStrings = strings.GroupBy(condition)
var stringsMeetingCondition = groupedStrings.FirstOrDefault(g => g.Key);
var stringsNotMeetingCondition = groupedStrings.FirstOrDefault(g => !g.Key);
var groupedStrings=strings.GroupBy(条件) var stringsMeetingCondition=groupedStrings.FirstOrDefault(g=>g.Key); var stringsNotMeetingCondition=groupedStrings.FirstOrDefault(g=>!g.Key);
Func条件=。。。;
var groupedStrings=strings.GroupBy(条件)
var stringsMeetingCondition=groupedStrings.FirstOrDefault(g=>g.Key);
var stringsNotMeetingCondition=groupedStrings.FirstOrDefault(g=>!g.Key);

Where
扩展方法抛出一个
IEnumerable
,但
RemoveAll
是一个就地操作。因此,您正在比较根本不同的操作。什么是“写作效率”?简洁、简洁、易懂?你说得不清楚。修改一个你有一个非物质化查询的列表时要非常小心。LINQ的延迟特性使得这是不可取的(尽管您的示例应该可以)什么是简洁的?什么是简洁的?:)(我不是英语母语)我的意思是容易阅读/理解。我的代码现在正确了吗?
Where
扩展方法抛出了一个
IEnumerable
,但是
RemoveAll
是一个就地操作。因此,您正在比较根本不同的操作。什么是“写作效率”?简洁、简洁、易懂?你说得不清楚。修改一个你有一个非物质化查询的列表时要非常小心。LINQ的延迟特性使得这是不可取的(尽管您的示例应该可以)什么是简洁的?什么是简洁的?:)(我不是英语母语)我的意思是容易阅读/理解。我的代码现在正确了吗?选择只返回一个列表,对吗?它是否也会修改原始列表实例?我的意思是,我需要得到两张清单。这会给我一个匹配条件和原始列表的项目列表,对吗?Select不会返回列表。它返回一个
IEnumerable
No,只返回一个IEnumerable。是否需要对原始列表进行变异?如果“变异”意味着更改,则可以对原始列表进行变异。选择仅返回一个列表,对吗?它是否也修改了原始列表inst