Salta la prima colonna e distinguiti dalle altre colonne
-
06-07-2019 - |
Domanda
Devo selezionare righe distinte dalla visualizzazione del file di testo di seguito.
File di testo
123| one| two| three <br/>
124| one| two| four <br/>
125| one |two| three <br/>
All'output dovrebbe piacere questo
123| one| two| three <br/>
124| one| two| four <br/>
OPPURE
124| one| two| four <br/>
125| one |two| three <br/>
Sto usando questo codice per risolvere questo 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()
Grazie
Soluzione
La spaziatura poco chiara nella domanda non aiuta ( in particolare attorno al | two |
, che ha una spaziatura diversa rispetto al resto, il che implica che dobbiamo usare il taglio) , ma ecco alcuni metodi LINQ personalizzati che fanno il lavoro. Ho usato il tipo anone semplicemente come un modo semplice per appiattire la spaziatura incoerente (avrei potuto anche ricostruire una stringa, ma sembrava inutile)
Nota che senza la spaziatura dispari, questo può essere semplicemente:
var qry = ReadLines("foo.txt")
.DistinctBy(line => line.Substring(line.IndexOf('|')));
Codice 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;
}
}
}
}
Altri suggerimenti
Dai un'occhiata, questo farà quello che vuoi fare
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 implementa IEqualityComparer in questo modo
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;
}
}
Ti darà l'output come ti aspettavi.