Ako rozhádzať DataTable

Ako rozhádzať DataTable

Nedávno som narazil na to, že potrebujem zobraziť nejaké dáta v náhodnom poradí pri každom zobrazení stránky.

MS SQL riešenie

Najprv som to chcel riešiť na úrovni MS SQL databázy.

MS SQL má funkciu RAND ktorá je ale dosť nepraktická a na tento účel nepoužiteľná. Napriek tomu existuje pomerne jednoduché riešenie:

  SELECT * FROM table ORDER BY NEWID()

Funkcia NEWID vygeneruje náhodný identifikátor pre každý riadok. Takže vďaka ORDER BY klauzule budú výsledky vždy v inom poradí. Dá sa to použiť aj v kombinácii s TOP klauzulou, napr.:

SELECT TOP(10) * FROM table WHERE cid < 1000 ORDER BY NEWID()

Nevýhodou je, že NEWID() sa generuje vždy pre každý jeden riadok celej tabuľky. V každom prípade je toto riešenie veľmi rýchle.

.NET riešenie

Ďaľšou možnosťou je rozhádzať výsledky na úrovni aplikácie.

Nasledujúca statická metóda dostane na vstup parameter typu DataTable a vráti nový DataTable s náhodne poprehadzovanými riadkami:

public static DataTable Randomize(DataTable dt)
{
	if (dt == null) throw new ArgumentNullException("dt");
	dt.AcceptChanges();
	//Vytvorím novú DataTable s rovnakou štruktúrou
	DataTable dtnew = dt.Clone();
	//Vytvorím nový DataView nad tabuľkou dt
	DataView dv = dt.DefaultView;

	Random r = new Random();
	int randomIndex = 0;
	while (dv.Count > 0)
	{
		//Vyberiem náhodný index (riadok)
		randomIndex = r.Next(0, dv.Count);
		//Pridám vybraný riadok do novej DataTable
		dtnew.Rows.Add(dv[randomIndex].Row.ItemArray);
		//Nastavím vybraný riadok zo starej DataTable na "vymazaný"
		dv.Delete(randomIndex);
	}

	//Zruším "vymazanie" riadkov
	dt.RejectChanges();

	dv = null;
	return dtnew;
}

Komentáre by mali byť jasné. Výhodou tohto prístupu je, že sa dá použiť viackrát nad už vytiahnutými dátami z DB. Taktiež je menej zaťažená databáza a dá sa použiť kedykoľvek ad-hoc.

Implementácia pre .NET 3.5

Ak používate .NET 3.5, môžete si túto metódu naimplementovať ako extension metódu nad DataTable:

public static class DataUtils
{
	public static DataTable Randomize(this DataTable dt)
	{
	    dt.AcceptChanges();
		//Vytvorím novú DataTable s rovnakou štruktúrou
		DataTable dtnew = dt.Clone();
		//Vytvorím nový DataView nad tabuľkou dt
		DataView dv = dt.DefaultView;
		
		Random r = new Random();
		int randomIndex = 0;
		while (dv.Count > 0)
		{
			//Vyberiem náhodný index (riadok)
			randomIndex = r.Next(0, dv.Count);
			//Pridám vybraný riadok do novej DataTable
			dtnew.Rows.Add(dv[randomIndex].Row.ItemArray);
			//Nastavím vybraný riadok zo starej DataTable na "vymazaný"
			dv.Delete(randomIndex);
		}

		//Zruším "vymazanie" riadkov
		dt.RejectChanges();

		dv = null;
		return dtnew;
	}
}

Potom môžeme použiť nasledovný jednoduchý zápis:

    DataTable random = dt.Randomize();

 

Ak máte iné skúsenosti s náhodným poradím dát, podeľte sa o ne v diskusii.

Update 6. 7. 2009

Dnes ma napadlo aj ďalšie riešenie, ako náhodne poprehadzovať riadky DataTable.

Najprv pridám nový stĺpec, dám doňho náhodné hodnoty a potom to podľa neho zotriedim. Na generovanie náhodných hodnôt použijem metódu Guid.NewGuid(), ktorá vždy vráti iný a náhodný identifikátor.

Tu je teda ďalšie riešenie:

public static class DataUtils
{
    public static DataTable RandomizeEx(this DataTable dt)
    {
        if (dt.Rows.Count == 0) return null;
        //vytvorim unikatny nazov stlpca, ktory bude obsahovat "nahodne" retazce
        string randomColumn = string.Format("Random_{0}", Guid.NewGuid());
        //pridam stlpec do tabulky
        dt.Columns.Add(randomColumn, typeof(string));

        //pre kazdy riadok pridam nahodny retazec - Guid
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            dt.Rows[i][randomColumn] = Guid.NewGuid().ToString();
        }
        //dam zotriedit DataView podla stlpca s nahodnymi hodnotami
        dt.DefaultView.Sort = randomColumn;
        //vratim novu DataTable zo zotriedeneho DataView
        return dt.DefaultView.ToTable();
    }
}

Skôr ako začneme: nahliadnite do spracovania vašich osobných údajov

Súbory cookies používame najmä na anonymnú analýzu návštevnosti a vylepšovanie našich web stránok. Ak si nastavíte blokovanie zápisu cookies do vášho prehliadača, je možné, že web sa spomalí a niektoré jeho časti nemusia fungovať úplne korektne. Viac info k spracúvaniu cookies.