我有一个跟踪列表,我需要遍历列表,看看列表中是否有相同的元素,只返回一个唯一的列表。任何人都可以让我知道以下代码的错误和正确的方法吗?
另外,Linq方式做到了,如果有的话?
预期的解决方案是= {{"a", "b", "c"},{"e", "b", "c" }}
class Program1
{
static void Main(string[] args)
{
List<string>[] stringLists = new List<string>[3]
{
new List<string>(){ "a", "b", "c" },
new List<string>(){ "e", "b", "c" },
new List<string>(){ "a", "b", "c" }
};
List<List<string>> prt = new List<List<string>>();
/* I DONT UNDERSTAND WHY THIS IS NOT WORKING !!!!!!!!!!!!!!! */
foreach (var item in stringLists)
{
for (int i = 0; i < item.Count; i++)
{
if (item == stringLists[i] && (!prt.Contains(item)))
{
prt.Add(item);
}
}
}
}
}
答案 0 :(得分:2)
您可以使用自定义 open_constr
尝试好的Distinct
:
IEqualityComparer<T>
...
using System.Linq;
...
public class SequenceComparer<T> : IEqualityComparer<IEnumerable<T>> {
public bool Equals(IEnumerable<T> x, IEnumerable<T> y) {
return Enumerable.SequenceEqual(x, y);
}
//TODO: Suboptimal HashCode implementation
public int GetHashCode(IEnumerable<T> obj) {
return obj == null
? 0
: obj.Count();
}
}
测试:
var stringLists = new List<string>() {
new List<string> {"a", "b", "c"},
new List<string> {"e", "b", "c"},
new List<string> {"a", "b", "c"}
};
// All you have to do is to put Distinct
var result = stringLists
.Distinct(new SequenceComparer<string>())
.ToList(); // If you want materialization
结果:
Console.Write(string.Join(Environment.NewLine, result
.Select(list => string.Join(", ", list))));
答案 1 :(得分:0)
prt.Contains(item)
表达式会将List
与引用与其元素进行比较,因此确定两个列表是否重复是一个错误的选择。
尝试以下
var stringLists = new List<string>[3]
{
new List<string> {"a", "b", "c"},
new List<string> {"e", "b", "c"},
new List<string> {"a", "b", "c"}
};
var prt = new List<List<string>>();
foreach (var item in stringLists)
{
if(prt.All(it => it.Count != item.Count || it.Except(item).Any()))
prt.Add(item);
}
答案 2 :(得分:0)
你需要在所有列表上做联合,而不是做一个明确的联盟。
像这样,只需遍历列表并将其与最后结果联合起来:
List<string> result = new List<string>();
foreach (var list in stringLists)
{
result = result.Union(list).ToList();
}
result = result.Distinct().ToList();
答案 3 :(得分:0)
Dmitry Bychenko的答案是要走的路。
对于您的特殊情况以及不包含,
的数据,您可以逃脱:
using System;
using System.Linq;
using System.Collections.Generic;
public class Program1
{
public static void Main()
{
var stringLists = new List<List<string>>{
new List<string> {"a", "b", "c"},
new List<string> {"e", "b", "c"},
new List<string> {"a", "b", "c"}
};
var prt = stringLists
.Select(l => string.Join(",", l)) // make it a string separated by ,
.Distinct() // distinct it using string.Distinct()
.Select(l => l.Split(',').ToList()); // split it again at , and make it List
foreach (var p in prt)
{
foreach (var c in p)
Console.WriteLine(c);
Console.WriteLine();
}
}
}
在这种方法中有很多不需要的对象创建 - 但我会工作(直到你的数据包含,
- 然后会混淆你的列表)。
输出:
a
b
c
e
b
c
答案 4 :(得分:0)
您的误解是您希望声明
true
在item
中已存在prt
中的字符串序列时返回Contains
。但是,void Main()
{
Console.Write( (new []{new []{ "a", "b", "c" }}).Contains(new[] { "a", "b", "c" }));
// Prints false
}
内部的测试用于确定这是一个引用相等,而不是逐项相等。这是一个最简单的例子来说明这一点:
class Program1
{
static void Main(string[] args)
{
List<string>[] stringLists = new List<string>[3]
{
new List<string>(){ "a", "b", "c" },
new List<string>(){ "e", "b", "c" },
new List<string>(){ "a", "b", "c" }
};
List<List<string>> prt = new List<List<string>>();
for(int i = 0; i < 3; i++)
{
bool isDifferentFromAllOthers = true;
for(int j = 0; j < i; j++)
{
bool isSameAsThisItem = true;
for(int item = 0; item < 3; item++)
{
// !!! Here is the explicit item by item string comparison
if (stringLists[i][item] != stringLists[j][item])
{
isSameAsThisItem = false;
break;
}
}
if (isSameAsThisItem)
{
isDifferentFromAllOthers = false;
break;
}
}
if (isDifferentFromAllOthers)
{
prt.Add(stringLists[i]);
}
}
// /* I DONT UNDERSTAND WHY THIS IS NOT WORKING !!!!!!!!!!!!!!! */
// foreach (var item in stringLists)
// {
// for (int i = 0; i < item.Count; i++)
// {
// if (item == stringLists[i] && (!prt.Contains(item)))
// {
// prt.Add(item);
// }
// }
// }
}
}
您需要使用深度等于比较器,如@Dmitry的答案,它会创建每个列表的摘要(哈希)并比较摘要,或明确地执行此操作,如下代码:
CREATE TRIGGER trg_newslistusers AFTER INSERT ON lisc_user_usergroup_map
FOR EACH ROW
INSERT IGNORE INTO lisc_acymailing_listsub
SELECT b.group_id, a.subid,UNIX_TIMESTAMP(), NULL, 1 FROM lisc_acymailing_subscriber a INNER JOIN lisc_user_usergroup_map b ON a.userid = b.user_id;