Omita la primera columna y diferencie de otras columnas
-
06-07-2019 - |
Pregunta
Necesito seleccionar filas distintas de la pantalla del archivo de texto a continuación.
Archivo de texto
123| one| two| three <br/>
124| one| two| four <br/>
125| one |two| three <br/>
La salida debería gustarle
123| one| two| three <br/>
124| one| two| four <br/>
O
124| one| two| four <br/>
125| one |two| three <br/>
Estoy usando este código para resolver este problema
var readfile = File.ReadAllLines(" text file location ");
var spiltfile = (from f in readfile
let line = f.Split('|')
let y = line.Skip(1)
select (from str in y
select str).FirstOrDefault()).Distinct()
Gracias
Solución
El espacio poco claro en la pregunta no ayuda ( especialmente alrededor del | two |
, que tiene un espacio diferente que el resto, lo que implica que debemos usar el recorte) , pero aquí hay algunos métodos personalizados de LINQ que hacen el trabajo. He usado el tipo anon puramente como una forma simple de aplanar el espaciado inconsistente (también podría haber reconstruido una cadena, pero parecía innecesario)
Tenga en cuenta que sin el espaciado impar, esto puede ser simplemente:
var qry = ReadLines("foo.txt")
.DistinctBy(line => line.Substring(line.IndexOf('|')));
Código completo:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
static class Program
{
static void Main()
{
var qry = (from line in ReadLines("foo.txt")
let parts = line.Split('|')
select new
{
Line = line,
Key = new
{
A = parts[1].Trim(),
B = parts[2].Trim(),
C = parts[3].Trim()
}
}).DistinctBy(row => row.Key)
.Select(row => row.Line);
foreach (var line in qry)
{
Console.WriteLine(line);
}
}
static IEnumerable<TSource> DistinctBy<TSource, TValue>(
this IEnumerable<TSource> source,
Func<TSource, TValue> selector)
{
var found = new HashSet<TValue>();
foreach (var item in source)
{
if (found.Add(selector(item))) yield return item;
}
}
static IEnumerable<string> ReadLines(string path)
{
using (var reader = File.OpenText(path))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
}
Otros consejos
Mira esto, esto hará lo que quieras hacer
static void Main(string[] args)
{
string[] readfile = System.IO.File.ReadAllLines(@"D:\1.txt");
var strList = readfile.Select(x => x.Split('|')).ToList();
IEnumerable<string[]> noduplicates =strList.Distinct(new StringComparer());
foreach (var res in noduplicates)
Console.WriteLine(res[0] + "|" + res[1] + "|" + res[2] + "|" + res[3]);
}
E implemente el IEqualityComparer de esta manera
class StringComparer : IEqualityComparer<string[]>
{
public bool Equals(string[] x, string[] y)
{
if (Object.ReferenceEquals(x, y)) return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
return x[1].Trim() == y[1].Trim() && x[2].Trim() == y[2].Trim() && x[3].Trim() == y[3].Trim() ;
}
public int GetHashCode(string[] data)
{
if (Object.ReferenceEquals(data, null)) return 0;
int hash1 = data[1] == null ? 0 : data[1].Trim().GetHashCode();
int hash2 = data[2] == null ? 0 : data[2].Trim().GetHashCode();
int hash3 = data[3] == null ? 0 : data[3].Trim().GetHashCode();
return hash1 ^ hash2 * hash3;
}
}
Te dará el resultado que esperabas.