例如,我有两个数组:
string[] arrayOne = {"One", "Two", "Three", "Three", "Three"};
string[] arrayTwo = {"One", "Two", "Three"};
var result = arrayOne.Except(arrayTwo);
foreach (string s in result) Console.WriteLine(s);
我想要来自arrayOne
的{{1}}中没有的项目。所以我需要结果为: arrayTwo
但是因为它治疗"三"一般而不检查其他两项("三","三")。
我不想写一个巨大的方法来解决这个问题。在SO上尝试了其他的答案,但没有按预期工作:(。
感谢!!!
答案 0 :(得分:5)
构建第二个HashSet,然后过滤第一个只允许项目,如果你不能从HashSet中删除项目。
int temp = _day;
_day = _day + 1;
_day = temp;
击> <击> 撞击>
考虑到评论中的额外要求,var hs = new HashSet<string>(arrayTwo);
var filtered = arrayOne.Where(item => !hs.Remove(item)).ToArray();
的一些漂亮用法在这里很有效。
ILookup
答案 1 :(得分:3)
答案取决于数组大小,重复元素数,代码速度的重要性。
对于小型数组,以下代码将是最简单和最好的:
List<string> result = new List<string>(arrayOne);
foreach (string element in arrayTwo)
result.Remove(element);
如果你想要更大的数组效率,你可以使用消费者的答案。
如果您想要最有效的代码,则必须手动编码以下算法: 1.对arrayOne和arrayTwo进行排序。 2.同时迭代两种算法(如在mergesort中)并省略具有相同元素的对。
Proc:没有沉重的Lookup对象 缺点:需要编码
答案 2 :(得分:2)
这样做的一种方法是包括索引以及:
var result = arrayOne.Select((r, i) => new {Value = r, Index = i})
.Except(arrayTwo.Select((r, i) => new {Value = r, Index = i}))
.Select(t => t.Value);
这将为您输入所需的输出,但上述方法的问题是,不同索引上的相同字符串将被区别对待。
忽略指数的另一种方法可以像:
string[] arrayOne = { "One", "Two", "Three", "Three", "Three", "X" };
string[] arrayTwo = { "One", "Two", "Three" };
var query1 = arrayOne.GroupBy(r => r)
.Select(grp => new
{
Value = grp.Key,
Count = grp.Count(),
});
var query2 = arrayTwo.GroupBy(r => r)
.Select(grp => new
{
Value = grp.Key,
Count = grp.Count(),
});
var result = query1.Select(r => r.Value).Except(query2.Select(r => r.Value)).ToList();
var matchedButdiffferentCount = from r1 in query1
join r2 in query2 on r1.Value equals r2.Value
where r1.Count > r2.Count
select Enumerable.Repeat(r1.Value, r1.Count - r2.Count);
result.AddRange(matchedButdiffferentCount.SelectMany(r=> r));
result
将包含{"X", "Three", "Three"}
答案 3 :(得分:2)
您可以通过向数组的每个元素添加索引来获得所需的输出,使其看起来像
{{ "One", 0 }, { "Two", 0 }, { "Three", 0 }, { "Three", 1 }, { "Three", 2 }}
{{ "One", 0 }, { "Two", 0 }, { "Three", 0 }}
然后您可以使用Except
删除重复项
var arrayOneWithIndex = arrayOne
.GroupBy(x => x)
.SelectMany(g => g.Select((e, i) => new { Value = e, Index = i }));
var arrayTwoWithIndex = arrayTwo
.GroupBy(x => x)
.SelectMany(g => g.Select((e, i) => new { Value = e, Index = i }));
var result = arrayOneWithIndex.Except(arrayTwoWithIndex).Select(x => x.Value);
答案 4 :(得分:1)
由于不需要最终输出的顺序,您可以在arrayOne
中对重复的字符串进行分组,并在arrayTwo
中分组减去计数(和当前)重复次数。然后,您可以再次展开集合,同时使用Enumerable.Repeat
复制迭代次数。
string[] arrayOne = {"One", "Two", "Three", "Three", "Three"};
string[] arrayTwo = {"One", "Two", "Three"};
var groupedTwo = arrayTwo
.GroupBy(g => g)
.ToDictionary(g => g.Key, g => g.Count());
var groupedResult = arrayOne
.GroupBy(a => a)
.Select(g => new {g.Key, Count = g.Count()})
.Select(g => new {g.Key, Residual = g.Count -
(groupedTwo.ContainsKey(g.Key) ? groupedTwo[g.Key] : 0)})
.SelectMany(g => Enumerable.Repeat(g.Key, g.Residual));
foreach (string s in groupedResult)
{
Console.WriteLine(s);
}
请注意,这显然不会保留原始顺序中可能发生的任何交错。
e.g。对于
string[] arrayOne = {"Three", "Four", "One", "Two", "Three", "Three"};
答案非直观地
Three
Three
Four
答案 5 :(得分:1)
迟到这个讨论,并在此处记录以供参考。 LINQ的Except方法使用默认的相等比较器来确定两个数组中哪些项匹配。在这种情况下,默认的相等比较器调用对象上的Equals方法。对于字符串,此方法已被重载以比较字符串的内容,而不是其标识(引用)。
这解释了为什么在这种特定情况下会发生这种情况。当然,它没有提供解决方案,但我相信其他人已经提供了出色的答案。 (实际上,这比评论更适合我。)
我可能提出的一个建议是编写自定义比较器,并将其传递给接受一个的Except重载。自定义比较器并不过分复杂,但考虑到您的场景,我了解您可能不希望这样做的地方。
答案 6 :(得分:0)
试试这个:
actions: {
submitForm() {
var inpObj = this.get('name');
if(!inpObj.checkValidity()) {
// error handling
alert('ok');
} else {
// save your data, or whatever you need to do
this.transitionTo('some.route');
}
}
}
击> <击> 撞击> 好的,如果这不起作用 - 我会更仔细地阅读评论。
以下代码:
var result = from s in first
where !string.IsNullOrWhiteSpace(s) &&
!second.Contains(s)
select s;
产生以下结果:
private static void Main(string[] args)
{
string[] first = {"One", "Two", "Three", "Three", "Three"};
string[] second = {"One", "Two", "Four", "Three"};
var result = FirstExceptSecond(first, second);
foreach (string s in result)
{
Console.WriteLine(s);
}
}
private static IEnumerable<string> FirstExceptSecond(IList<string> first, IList<string> second)
{
List<string> firstList = new List<string>(first);
List<string> secondList = second as List<string> ?? second.ToList();
foreach (string s in secondList)
{
if (firstList.Contains(s))
{
firstList.Remove(s);
}
}
return firstList;
}
答案 7 :(得分:0)
使用LINQ比较数组相等性的另一种方法如下。
LINQ中使用的逻辑: 在这段代码中,我正在过滤第一个数组元素,以使第一个数组中的每个元素都等于第二个数组中的对应元素,并且第一个数组的当前索引存在于第二个数组中;如果要比较的两个数组相等,则此过滤将导致元素数量与第一个数组中的元素数量相同。
string[] arrayOne = {"One", "Two", "Three", "Three", "Three"};
string[] arrayTwo = {"One", "Two", "Three"};
bool result =(arrayOne.Where((string n, int i) => i <= (arrayTwo.Length-1) &&
n == arrayTwo[i]).Count() == arrayOne.Length);
//if result == true then arrays are equal else they are not