您好我正在尝试在从XML文件填充的两个dataGridView表中查找唯一字符串。我所做的代码运行没有问题,但它无法检测我何时在其中一个表中更改字符串(使其唯一)。我的逻辑有什么问题吗?
private void button5_Click(object sender, EventArgs e)
{
string[] column1 = new string[dataGridView1.Rows.Count];
string[] column2 = new string[dataGridView2.Rows.Count];
int unique = 0;
bool found = false;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
column1[i] = Convert.ToString(dataGridView1.Rows[i].Cells[2].Value);
}
for (int i = 0; i < dataGridView2.Rows.Count; i++)
{
column2[i] = Convert.ToString(dataGridView2.Rows[i].Cells[2].Value);
}
for (int i = 0; i < column1.Length; i++)
{
for (int j = 0; j < column2.Length; j++)
{
if (column1[i] == column2[j])
{
found = true;
}
}
if (found == false)
{
unique++;
found = false;
}
}
MessageBox.Show(unique + " unique strings found!");
}
最终解决方案需要能够返回包含唯一字符串的单元格,以便我可以向用户突出显示它们。非常感谢你的帮助!
答案 0 :(得分:3)
简单使用linq:
array1.Except(array2).Concat(array2.Except(array1))
在回复您的注释时,您可以使用两个左连接模拟完整的外连接,并在输出中查找空值。在另一侧不匹配的连接的任何一侧都可以被认为是唯一的。使用以下扩展名进行连接:
public static class LinqEx
{
public static IEnumerable<TResult>
LeftOuterJoin<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector)
{
return outer
.GroupJoin(
inner,
outerKeySelector,
innerKeySelector,
(a, b) => new
{
a,
b
})
.SelectMany(
x => x.b.DefaultIfEmpty(),
(x, b) => resultSelector(x.a, b));
}
public static IEnumerable<TResult>
FullOuterJoin<TSet1, TSet2, TKey, TResult>(
this IEnumerable<TSet1> set1,
IEnumerable<TSet2> set2,
Func<TSet1, TKey> set1Selector,
Func<TSet2, TKey> set2Selector,
Func<TSet1, TSet2, TResult> resultSelector)
{
var leftJoin = set1.
LeftOuterJoin(
set2,
set1Selector,
set2Selector,
(s1, s2) => new {s1, s2});
var rightJoin = set2
.LeftOuterJoin(
set1,
set2Selector,
set1Selector,
(s2, s1) => new {s1, s2});
return leftJoin.Union(rightJoin)
.Select(x => resultSelector(x.s1, x.s2));
}
}
然后,您可以创建捕获附加数据的匿名对象,例如项目的索引及其来源,以及外部连接。连接两侧的项目结果将被过滤掉(因为它们存在于两个集合中),因此结果集现在只包含其中一个集合唯一的项目。
void Main()
{
var set1 = new[] {"a", "b", "c"};
var set2 = new[] {"b", "c", "d", "d"};
var annotatedSet1 = set1
.Select((item,index) => new {src = "set1", index, item});
var annotatedSet2 = set2
.Select((item,index) => new {src = "set2", index, item});
var uniques = annotatedSet1
.FullOuterJoin(
annotatedSet2,
x => x.item,
x => x.item,
(s1, s2) => new {s1, s2})
.Where(x => x.s1 == null || x.s2 == null)
.Select(x => x.s1 ?? x.s2);
}
会产生结果:
{src="set1", index=0, item="a"}
{src="set2", index=2, item="d"}
{src="set2", index=3, item="d"}
答案 1 :(得分:0)
您可以使用链接运算符,Union和Distinct运算符
var temp = column1.Union(column2);
var result = temp.Distinct();
答案 2 :(得分:0)
这是Linq与Enumerable.Except
:
var dg1Cell2 = dataGridView1
.Rows.Cast<DataGridViewRow>()
.Select(r => r.Cells[2].Value.ToString());
var dg2Cell2 = dataGridView1
.Rows.Cast<DataGridViewRow>()
.Select(r => r.Cells[2].Value.ToString());
var uniqueInDG1 = dg1Cell2.Except(dg2Cell2);
var result = from r in dataGridView1.Rows.Cast<DataGridViewRow>()
join u in uniqueInDG1 on r.Cells[2].Value.ToString() equals u
select r;
Except
产生一组差异,因此只保留第一个序列中的唯一字符串。然后我将结果加入DataGridViewRows
。
它比看起来效率更高,因为它全部是懒惰地执行,除了在内部使用set
并且linq-to-objects中的join
也是very efficient。
答案 3 :(得分:0)
感谢您的所有回复,但简单的回答是我没有在正确的点重置找到的值为false。我很欣赏您的解决方案所付出的努力,但它们对我的知识水平来说太复杂了。
以下是经过调整的代码:
private void button5_Click(object sender, EventArgs e)
{
string[] column1 = new string[dataGridView1.Rows.Count];
string[] column2 = new string[dataGridView2.Rows.Count];
int unique = 0;
bool found = false;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
column1[i] = Convert.ToString(dataGridView1.Rows[i].Cells[2].Value);
}
for (int i = 0; i < dataGridView2.Rows.Count; i++)
{
column2[i] = Convert.ToString(dataGridView2.Rows[i].Cells[2].Value);
}
for (int i = 0; i < column1.Length; i++)
{
for (int j = 0; j < column2.Length; j++)
{
if (column1[i] == column2[j])
{
found = true;
}
}
if (found == false)
{
unique++;
}
found = false;
}
MessageBox.Show(unique + " unique strings found!");
}
答案 4 :(得分:0)
以下代码将从 2 个字符串数组中返回不同的字符串数组
public string[] UniqueNames(string[] names1, string[] names2) {
newName = names1.ToList();
foreach (var dr in names2) {
if (!newName.Contains(dr)) {
newName.Add(dr);
}
}
string[] newNameArray = newName.ToArray();
return newNameArray;
}
或者你也可以试试,
public string[] UniqueNames(string[] names1, string[] names2) {
return names1.Union(names2).ToArray(); ;
}