Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.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#_String_List_Duplicates_Removeall - Fatal编程技术网

C# 如何从另一个列表中删除列表中的字符串?

C# 如何从另一个列表中删除列表中的字符串?,c#,string,list,duplicates,removeall,C#,String,List,Duplicates,Removeall,我有两张名单,分别是listA和listB 我想删除listB中listA中的字符串,但我想这样做: 如果listA包含:“bar”、“bar”、“bar”、“foo” listB包含:“bar” 它仅移除1个条,结果将是: “酒吧”、“酒吧”、“富” 我编写的代码删除了所有“条”: List result=listA.Except(listB.ToList(); 您可以尝试逐个删除它: foreach (var word in listB) listA.Remove(word); R

我有两张名单,分别是listA和listB

我想删除listB中listA中的字符串,但我想这样做:

如果listA包含:“bar”、“bar”、“bar”、“foo” listB包含:“bar”

它仅移除1个条,结果将是: “酒吧”、“酒吧”、“富”

我编写的代码删除了所有“条”:

List result=listA.Except(listB.ToList();

您可以尝试逐个删除它:

foreach (var word in listB)
    listA.Remove(word);
Remove方法一次只删除一个元素,并且在找不到项时不会引发异常(但返回false):

var listA=new List(){“bar”、“bar”、“bar”、“foo”};
var listB=new List(){“bar”};
foreach(列表B中的var字){
删除(word);
}

这是一种更快的方法,但可能会更改第一个列表中元素的顺序。步骤:

  • 将listA映射到一个
    字典
    (我们称之为
    listAMap
    ),其中key是列表的元素,value是该值在listA中出现的总次数
  • 迭代listB,对于listB的每个元素,如果该元素位于
    listAMap
    中,则减少其计数
  • 使用C#字典获取
    listMapA
    的键,并遍历所有键。对于每个具有正值的键,将该键添加到另一个列表,并记录其总计数次数。因此,如果条目是
    “bar”->2
    ,则在新列表中添加两次“bar”
该算法的总运行时间为O(m+n),其中m和n是两个原始列表中的元素数。它的运行时间比这里提到的其他具有O(m*n)运行时间的方法要好。显然,该算法使用了更多的空间


上述算法的支持代码:

//Step-1: Create the dictionary...
var listAMap = new Dictionary<string, int>();
foreach (var listAElement in listA)
{
    listAMap.ContainsKey(listAElement) ? listAMap[listAElement]++ : listAMap.Add(listAElement, 1);
}

// Step-2: Remove the listB elements from dictionary...
foreach (var listBElement in listB)
{
    if (listAMap.Contains(listBElement)) listAMap[listBElement]--;
}

//Step-3: Create the new list from pruned dictionary...
var prunedListA = new List<string>();
foreach (var key in listAMap.Keys)
{
    if (listAMap[key] <= 0) continue;
    for (var count = 0; count < listAMap[key]; count++)
    {
        prunedListA.Add(key);
    }
}

//prunedListA contains the desired elements now.
//步骤1:创建字典。。。
var listAMap=新字典();
foreach(listA中的var listAElement)
{
listAMap.ContainsKey(listAElement)?listAMap[listAElement]+:listAMap.Add(listAElement,1);
}
//步骤2:从字典中删除listB元素。。。
foreach(列表B中的var listBElement)
{
如果(listAMap.Contains(listBElement))listAMap[listBElement]--;
}
//步骤3:从修剪过的字典创建新列表。。。
var prunedListA=新列表();
foreach(listAMap.Keys中的var键)
{

如果(listAMap[key],这里有一种更有效的方法:

var countB = new Dictionary<string, int>(listB.Count);
foreach (var x in listB)
{
    int count;
    countB.TryGetValue(x, out count);
    countB[x] = count + 1;
}
listA.RemoveAll(x =>
{
    int count;
    if (!countB.TryGetValue(x, out count)) return false;
    if (count == 1)
        countB.Remove(x);
    else
        countB[x] = count - 1;
    return true;
});
var countB=新字典(listB.Count);
foreach(列表B中的变量x)
{
整数计数;
countB.TryGetValue(x,out count);
countB[x]=计数+1;
}
listA.RemoveAll(x=>
{
整数计数;
如果(!countB.TryGetValue(x,out count))返回false;
如果(计数=1)
b.删除(x);
其他的
countB[x]=计数-1;
返回true;
});

您可以避免使用直接IndexOf获取位置的Contains调用。这样做效率很低,但您至少可以直接使用
listA.Remove(word)
。不需要
包含
。保留一些原始列表的顺序是否重要?这基本上是@Ian答案的副本,发布10多分钟后,您才想到类似的内容,但计算列表B,然后从列表a中删除匹配的项目(并减少匹配计数).无论如何,+1表示考虑效率。@IvanStoev:我们没有匹配列表中的项目。我们在字典中进行O(1)查找。说真的,解决方案非常简单(不是说你可以在答案上给出+2)。我也应该添加代码。当我从笔记本电脑访问时,我会这样做。@IvanStoev:现在需要做的最后一件事是将上面的代码分解成一个单独的方法,这样它会更干净。很好。但让我发布我想到的算法。正如我所说,类似的想法是O(m+n),但没有你所说的重新排序效果。顺便说一句,我不打算发布它,因为大多数人都喜欢一行,不关心性能。但一旦你分享了你的想法:)你错过了填充countB的步骤。@displayName我没有-试试看(提示-小行
countB[x]=count+1;
):)哦,我明白了……我不知道字典中
TryGetValue()
的这种行为。学到了一些新东西。
//Step-1: Create the dictionary...
var listAMap = new Dictionary<string, int>();
foreach (var listAElement in listA)
{
    listAMap.ContainsKey(listAElement) ? listAMap[listAElement]++ : listAMap.Add(listAElement, 1);
}

// Step-2: Remove the listB elements from dictionary...
foreach (var listBElement in listB)
{
    if (listAMap.Contains(listBElement)) listAMap[listBElement]--;
}

//Step-3: Create the new list from pruned dictionary...
var prunedListA = new List<string>();
foreach (var key in listAMap.Keys)
{
    if (listAMap[key] <= 0) continue;
    for (var count = 0; count < listAMap[key]; count++)
    {
        prunedListA.Add(key);
    }
}

//prunedListA contains the desired elements now.
var countB = new Dictionary<string, int>(listB.Count);
foreach (var x in listB)
{
    int count;
    countB.TryGetValue(x, out count);
    countB[x] = count + 1;
}
listA.RemoveAll(x =>
{
    int count;
    if (!countB.TryGetValue(x, out count)) return false;
    if (count == 1)
        countB.Remove(x);
    else
        countB[x] = count - 1;
    return true;
});