Comparando dos hashsets

Tengo dos hashsets que están cargando datos de dos archivos de texto diferentes. El contenido de ambos archivos de texto tiene el siguiente aspecto:

name/12441431252132
name1/323244231244142
name2/32423452524234

Mi código para cargar actualmente ambos archivos y asegurarme de que solo tenga resultados únicos de textFile2:

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

txt2.ExceptWith(txt1); 

Mi problema es que solo elimina líneas según los criterios si coincide toda la línea. En su lugar, quiero eliminarlo según el nombre. Por ejemplo, name2 nunca debe incluirse si está en textFile1, incluso si los id después de / son diferentes.

¿Cómo lograría esto?

Avíseme si mi explicación no es buena, intentaré mejorarla, ¡y disculpe mi inglés!

preguntado el 22 de mayo de 12 a las 16:05

¿Los nombres en cada archivo de texto son únicos? -

No siempre puede haber más de 1 de lo mismo en textfile1, pero si es así, nunca debe incluirse después de ExceptWith en txt2:

3 Respuestas

Simplemente puede agregar un poco de división de cadenas para separar los nombres y el resto del contenido: el enfoque es un poco "sucio", por lo que en el código real probablemente usaría bucles foreach e introduciría clases dedicadas:

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]));

contestado el 22 de mayo de 12 a las 16:05

¿Cómo obtendría el primer nombre e ID únicos de la var única? más adelante en el código, necesito usar los primeros y convertirlos en cadenas: hariette

@hariette: No estaba claro para mí si quería separar las líneas en pares Nombre/Valor para txt2 también; en ese caso, solo use el mismo enfoque que se usó para el contents análisis - Vidrio roto

si te divides por /, puede crear un HashSet de nombres que aparecen en el primer conjunto y luego seleccionar los elementos del segundo conjunto que tienen un nombre que no aparece en el primer conjunto.

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);

contestado el 22 de mayo de 12 a las 16:05

¿Estás seguro de que un HashSet sigue siendo la mejor opcion? Aquí hay un enfoque diferente usando un 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);
    }
}

contestado el 22 de mayo de 12 a las 16:05

Eso es problemático, dado que el OP establece que los nombres en un archivo son no único. - donante

@spender: Pero su requisito es filtrar los nombres duplicados. El enfoque anterior anularía los números de nombres existentes, pero podría cambiarse fácilmente para hacer otra cosa. - Tim Schmelter

@spender: dado que OP solo quiere tomar el primero, he editado arriba para verificar la existencia con ContainsKey. - Tim Schmelter

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.