2012-05-22 128 views
2

我有两个散列集正在加载来自两个不同文本文件的数据。 这两个文本文件的内容如下所示:比较两个散列集

name/12441431252132 
name1/323244231244142 
name2/32423452524234 

我的代码到当前加载两个文件,并确保我只有从textFile2独特的结果:

HashSet<string> txt1 = new HashSet<string>(File.ReadLines("textFile1.txt")); 
HashSet<string> txt2 = new HashSet<string>(File.ReadLines("textFile2.txt")); 

txt2.ExceptWith(txt1); 

我的问题是,它不仅能消除如果整行匹配则基于标准。我想根据名称的基础去掉它。例如,如果name2在textFile1中,即使id在/之后不同,也不应包含它。

我该如何做到这一点?

让我知道如果我的解释不好,我会尽力改善它 - 请原谅我的英语!

+0

每个文本文件中的名称是唯一的吗? – spender

+0

在textfile1中并不总是可以有多于1个,但是如果是这样的话,它应该永远不会包含在txt2中的ExceptWith之后 – hariette

回答

3

您可以再补充一些字符串分割到不同的名称和内容的其余部分 - 的做法是有点“脏”,所以在实际的代码,我可能会使用foreach循环和引进专用类:

var content = File.ReadLines("textFile1.txt").Select(line => 
{ 
    var parts = line.Split('/'); 
    return new 
    { 
     Name = parts[0], 
     Content = parts[1] 
    }; 
}); 

HashSet<string> names = new HashSet<string>(content.Select(c=> c.Name)); 
HashSet<string> txt2 = new HashSet<string>(File.ReadLines("textFile2.txt")); 
var uniques = txt2.Where(line => !names.Contains(line.Split('/')[0])); 
+0

如何从uniques var获取第一个唯一的名称和ID?在后面的代码中,我需要使用第一个字符串,并将它们转换为字符串 – hariette

+0

@hariette:我不清楚你是否想将'txt2'的行分隔到Name/Value对中 - case只是使用与'contents'解析相同的方法 – BrokenGlass

0

如果按/分割,则可以构建出现在第一个集合中的名称的HashSet,然后选择第二个集合中名称不出现在第一个集合中的项目。

var nameValues1= 
    File 
    .ReadLines(fileName) 
    .Select(line=>line.Split('/')) 
    .Select(parts=>new {name=parts[0],value=parts[1]}); 
var nameValues2= 
    File 
    .ReadLines(fileName2) 
    .Select(line=>line.Split('/')) 
    .Select(parts=>new {name=parts[0],value=parts[1]}); 
var names1=new HashSet<string>(nameValues1.Select(nv=>nv.name); 
var result= 
    nameValues2 
    .Where(nv=>!names1.Contains(nv.name)) 
    .Select(nv=>string.Format("{0}/{1}",nv.name,nv.value); 
0

您确定HashSet仍然是最佳选择吗?这是一个不同的方法使用Dictionary<String, String>

var lines1 = System.IO.File.ReadLines(path1); 
var lines2 = System.IO.File.ReadLines(path2); 
var allItems = new Dictionary<String, String>(); 
foreach (var line in lines1.Concat(lines2)) 
{ 
    String[] tokens = line.Split('/'); 
    if (tokens.Length == 2) 
    { 
     String name = tokens[0]; 
     String number = tokens[1]; 
     if (!allItems.ContainsKey(name)) 
      allItems.Add(name, number); 
    } 
} 
+0

这是有问题的,因为OP声明文件中的名称不是**唯一的。 – spender

+0

@spender:但他的要求是过滤出重复的名字。上述方法将覆盖现有名称的数字,但可以轻松更改以执行其他操作。 –

+1

@spender:由于OP只是想采取第一,我已经编辑上面检查存在'ContainsKey'。 –