Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailemVyřešeno Linq - dotaz na řešení problému

Ahoj,
prosil bych o radu.
Mám načtené v Linqu data. Problém je trošku složitější, proto se snažím uvádět jen to nejpodstatnější.
V Linqu zatím znám základy a toto se týká porovnávání dat.

Řekněme, že mám v Linqové proměnné načtenu následující tabulku dat:
917152976
A nyní dostanu další soubor - tedy "další" Linqovou proměnnou (tabulku):
565050002

Potřeboval bych navrhnout Linqový dotaz, který bude schopen porovnat tyto dvě proměnné navzájem podle následujících kriterií:

-Zjistit, co je nového (které položky přibyly)
-Zjistit, co ubylo (které položky už nejsou ve druhém souboru)
-Zjistit, u kterých položek se změnilo množství (tj. sloupeček délka)

na zákldadě předchozích bodů:
-Vytvořit třetí Linqovou proměnnou (tabulku), která bude obsahovat podle předchozích bodů:
-odmazané staré řádky, které v tabulce číslo jedna jsou navíc oproti tabulce dva.
-přidané nové řádky, které jsou v tabulce dva navíc

Věřím, že to není složité, jen se to snažím dobře a klidně i příliš podrobně popsat.
Prostě v další tabulce chybí "hadice" 101 a 102 a je tam jen navíc sklo a papir.

Děkuji za přečtení a případné návrhy.

Předmět Autor Datum
A určitě to potřebuješ jedním dotazem?
Wikan 05.05.2014 11:14
Wikan
Klidně to může být realizováno i více dotazy. Hlavně abych se posunul k "cíli" :-) Zatím jsem zkonč…
Console 05.05.2014 11:45
Console
var textRecordsNotInFirstFile = records1L.Where(t => !records2L.Any(r => t.vendor_mat_number == r.ve…
Wikan 05.05.2014 11:55
Wikan
Výborně, upravil jsem to následně: string path = "newFile.csv"; string path2 = "newFile2.csv"; if…
Console 05.05.2014 12:30
Console
No a kde je problém? Seznam je prázdný, nebo je chyba v zápisu do souboru?
Wikan 05.05.2014 12:35
Wikan
Seznam je prázdný. Respektive dotaz: records1L.Where(t => !records2L.Any(r => r.polozka == t.polozka…
Console 05.05.2014 12:40
Console
A obě prohledávané kolekce, to jest records1L a records2L obsahují každá 12 záznamů. Tam taky chyba…
Console 05.05.2014 12:45
Console
Jakého typu je "polozka" a je při načtení z CSV správně vyplněná?
Wikan 05.05.2014 13:22
Wikan
Je typu string. Celá třída vypadá takto: public class CustomClass { public int LineNo { get; set; }…
Console 05.05.2014 13:32
Console
Aha, no problém je minimálně v tom, že ten dotaz vrací položky, které jsou v prvním ale ne ve druhém…
Wikan 05.05.2014 13:48
Wikan
Upravil jsem to takto, ale zase to vrací nesmyslně moc položek var textRecordsNotInFirstFile = reco…
Console 05.05.2014 14:08
Console
Smazal jsi vykřičník.
Wikan 05.05.2014 15:11
Wikan
Ano. Ale records2L.Where(t => !records1L.Any(r => t.polozka == r.polozka)).ToList(); stejně vrací nu…
Console 05.05.2014 15:15
Console
Už jsem na to přišel. Se stydím ! Na vině byla špatně napsaná funkce ReadRecords, která otevírala je…
Console 05.05.2014 15:39
Console
Tady se vlákna nezavírají, pokud neporušují pravidla, nejsou duplicitní apod.
Wikan 05.05.2014 15:47
Wikan
Tak nevím, mám tenhle testovací kód: void Main() { var list1 = new List<Dummy> { new Dummy { Polozk…
Wikan 05.05.2014 15:46
Wikan
Jj. Díky moc. poslední
Console 05.05.2014 15:59
Console

Klidně to může být realizováno i více dotazy.
Hlavně abych se posunul k "cíli" :-)

Zatím jsem zkončil u tohoto:
(využívám rozšíření CsvHelper)

            string path = "newFile.csv";
            string path2 = "newFile2.csv";

            if (!File.Exists(path)) throw new FileNotFoundException(path);
            IEnumerable<CustomClass> records1 = ReadRecords(path);  // načte první soubor

            if (!File.Exists(path)) throw new FileNotFoundException(path2);
            IEnumerable<CustomClass> records2 = ReadRecords(path2); // načte druhý soubor

            var records1L = records1.ToList();  // převede do LINQ

            var records2L = records2.ToList();  // Převede do LINQ
           /* Následující kód by měl zjistit "diference", tedy to co není v souboru1, ale je v souboru2
Bohužel to hlásí: 
            The best overloaded method match for 'System.Collections.Generic.List<Ale.Form1.CustomClass>.Contains(Ale.Form1.CustomClass)' has some invalid arguments */
            var textRecordsNotInFirstFile = records1L.Where(t => !records2L.Any(t.vendor_mat_number != )).ToList();   

            TextWriter writer = File.CreateText("diference.csv");
            using (var csvWriter = new CsvHelper.CsvWriter(writer))
            {
                csvWriter.WriteRecords(textRecordsNotInFirstFile);  // mělo by zapsat rozdíly do souboru
            }

Zkoušel jsem googlovat, ale máš pravdu v tom, že odpovědi na tento dotaz bývají spletité.

Výborně, upravil jsem to následně:

            string path = "newFile.csv";
            string path2 = "newFile2.csv";

            if (!File.Exists(path)) throw new FileNotFoundException(path);
            IEnumerable<CustomClass> records1 = ReadRecords(path);

            if (!File.Exists(path)) throw new FileNotFoundException(path2);
            IEnumerable<CustomClass> records2 = ReadRecords(path2);

            var records1L = records1.ToList();

            var records2L = records2.ToList();

            var textRecordsNotInFirstFile = records1L.Where(t => !records2L.Any(r => t.polozka == r.polozka)).ToList();

            TextWriter writer = File.CreateText("diference.csv");
           
            using (var csvWriter = new CsvHelper.CsvWriter(writer))
            {
                csvWriter.Configuration.Delimiter = ";";
                csvWriter.WriteRecords(textRecordsNotInFirstFile);
            }

Program proběhne bez chyby, ale výsledný soubor diference.csv je prázdný.
Přitom očekávám, že bude obsahovat řádky s názvy sklo a papir, protože ty jsou ve druhém souboru navíc.

Je typu string. Celá třída vypadá takto:

public class CustomClass
        {
            public int LineNo { get; set; }
            public int Total { get; set; }
            public string Nazev { get; set; }
            public string rozmer { get; set; }
            public string polozka { get; set; }
            public string vendor_mat_number { get; set; }
            public string delka { get; set; }
            //added in demo
            public string TridiciZnak { get; set; }
            public int? NewNo { get; set; }
        }

Všechny hodnoty "polozka" v obou sloupcích jsou vyplněny.
Porovnávám ty předložené soubory, tam to lze vidět.

Ano. Ale records2L.Where(t => !records1L.Any(r => t.polozka == r.polozka)).ToList();
stejně vrací nula záznamů.

Mám pocit jakoby problém byl jinde. Zkoušel jsem i:
from c in records2L where !records1L.Any(w => w.polozka == c.polozka) select c;

což opět vrací nula záznamů. Asi jsme přehlédli nějakou jinou prkotinku.]:(

Už jsem na to přišel. Se stydím !
Na vině byla špatně napsaná funkce ReadRecords, která otevírala jeden pevný soubor a mezi ním nebyl samozřejmě žádný rozdíl!

Díky Wikanovi a poradna.net !

zatím tohle vlákno nezavírejte, možná se ještě na něco zeptám.:-D

Tak nevím, mám tenhle testovací kód:

void Main()
{
	var list1 = new List<Dummy> { 
		new Dummy { Polozka = "a" },
		new Dummy { Polozka = "b" },
		new Dummy { Polozka = "c" },
		new Dummy { Polozka = "d" }
	};
	var list2 = new List<Dummy> {
		new Dummy { Polozka = "a" },
		new Dummy { Polozka = "b" },
		new Dummy { Polozka = "e" },
		new Dummy { Polozka = "f" }
	};
	
	var diff1 = list1.Where(t => !list2.Any(r => t.Polozka == r.Polozka));
	var diff2 = list2.Where(t => !list1.Any(r => t.Polozka == r.Polozka));
	
	Console.WriteLine(diff1);
	Console.WriteLine(diff2);
}

public class Dummy 
{
	public string Polozka { get; set; }
}

Který vypisuje:

IEnumerable<Dummy> (2 items)
Polozka
c
d

IEnumerable<Dummy> (2 items)
Polozka
e
f

Teda přesně to, co bych od toho očekával.

Zpět do poradny Odpovědět na původní otázku Nahoru