Jak inicializovat List <T> k dané velikosti (na rozdíl od kapacity)?

hlasů
75

NET nabízí obecný seznam kontejner, jehož výkon je téměř totožný (viz Výkon polí vs. seznamy otázku). Nicméně oni jsou zcela odlišné v inicializaci.

Pole jsou velmi snadno inicializovat s výchozí hodnotou, a definice, které již mají určitou velikost:

string[] Ar = new string[10];

Která umožňuje, aby jeden bezpečně přiřadit náhodné předměty, říkají:

Ar[5]=hello;

se seznamem věci jsou složitější. Vidím dva způsoby, jak dělat stejný inicializace, žádný z nich je to, co byste nazvali elegantní:

List<string> L = new List<string>(10);
for (int i=0;i<10;i++) L.Add(null);

nebo

string[] Ar = new string[10];
List<string> L = new List<string>(Ar);

Jaký by měl být čistší způsob?

EDIT: Odpovědi dosud se týkají schopnosti, což je něco jiného než předvyplňujete seznamu. Například v seznamu právě vytvořili s kapacitou 10, jeden nemůže dělatL[2]=somevalue

EDIT 2: Lidé se diví, proč chci používat seznamy tímto způsobem, protože to není způsob, jakým mají být použity. Vidím dva důvody:

  1. Dalo by se velmi přesvědčivě argumentovat, že seznamy jsou „nové generace“ soustavy s tím, flexibilitu téměř bez trestu. Proto jedna je měli používat jako výchozí. Jsem poukázal na to nemusí být tak snadné inicializovat.

  2. To, co jsem v současné době psaní je základní třída oběť výchozí funkčnost jako součást většího rámce. Ve výchozím funkčnosti I nabízejí, je velikost seznamu je známý v moderní a proto jsem mohl použít pole. Nicméně, chci nabídnout jakékoliv základní třída šanci ji dynamicky rozšiřovat a proto se rozhodnou pro seznamu.

Položena 21/01/2009 v 21:54
zdroj uživatelem
V jiných jazycích...                            


15 odpovědí

hlasů
25

Pomocí konstruktor, která bere int ( „kapacita“) jako parametr:

List<string> = new List<string>(10);

EDIT: Měl bych dodat, že jsem se Frederik souhlasit. Používáte seznamu takovým způsobem, který jde proti celému důvodech jeho použití na prvním místě.

EDIT2:

EDIT 2: Co jsem v současné době psaní je základní třída oběť výchozí funkčnost jako součást většího rámce. Ve výchozím funkčnosti I nabízejí, je velikost seznamu je známý v moderní a proto jsem mohl použít pole. Nicméně, chci nabídnout jakékoliv základní třída šanci ji dynamicky rozšiřovat a proto se rozhodnou pro seznamu.

Proč by někdo potřebovat znát velikosti seznamu se všemi hodnotami null? Pokud nejsou k dispozici skutečné hodnoty v seznamu, tak bych očekávat, že délka bude 0. V každém případě skutečnost, že se jedná cludgy prokáže, že jde proti zamýšlené použití třídy.

Odpovězeno 21/01/2009 v 21:56
zdroj uživatelem

hlasů
7

Proč jste s použitím seznamu, chcete-li ji inicializovat s pevnou hodnotou? Chápu, že -při kvůli výkonově chcete dát mu počáteční kapacitu, ale ani jeden z výhod seznamu nad pravidelným souborem, že může růst v případě potřeby?

Když toto:

List<int> = new List<int>(100);

Je-li vytvořit seznam, jehož kapacita je 100 celá čísla. To znamená, že seznam nebude muset ‚růst‘, dokud přidat 101. bod. Základní pole seznamu se inicializuje s délkou 100.

Odpovězeno 21/01/2009 v 21:57
zdroj uživatelem

hlasů
5

Inicializace obsah seznamu, jako to není opravdu to, co seznamy jsou pro. Seznamy jsou navrženy tak, aby držet objekty. Pokud si chcete mapovat konkrétní čísla k jednotlivým objektům, zvažte použití struktury páru klíč-hodnota jako hashovací tabulky nebo slovníku namísto seznamu.

Odpovězeno 21/01/2009 v 21:59
zdroj uživatelem

hlasů
60

Nemůžu říct, že musím to velmi často - mohl byste dát více informací o tom, proč chcete to? Asi bych dal to jako statické metody v pomocník třídy:

public static class Lists
{
    public static List<T> RepeatedDefault<T>(int count)
    {
        return Repeated(default(T), count);
    }

    public static List<T> Repeated<T>(T value, int count)
    {
        List<T> ret = new List<T>(count);
        ret.AddRange(Enumerable.Repeat(value, count));
        return ret;
    }
}

Byste mohli použít Enumerable.Repeat(default(T), count).ToList(), ale to by bylo neefektivní kvůli vyrovnávací paměti změny velikosti.

EDIT: Jak je uvedeno v komentáři, můžete provést Repeatedpomocí smyčku k naplnění seznamu, pokud jste chtěli. Že by o něco rychleji příliš. Já osobně najít kód pomocí Repeatvýstižnější a podezření, že v reálném světě Rozdíl ve výkonnosti bude irelevantní, ale váš najetých kilometrů se mohou lišit.

Odpovězeno 21/01/2009 v 22:00
zdroj uživatelem

hlasů
1

To opravdu záleží na tom, proč ji chcete inicializovat. Nejsem si jistý, jeho inicializaci s určitým počtem prázdných nebo nulových prvků je užitečný. Výhoda seznamů je, že může růst podle potřeby.

Seznam konstruktor přebírá parametr kapacity, které lze použít pro to nejprve naplnit.

List<string> = new List<string>(10);
Odpovězeno 21/01/2009 v 22:01
zdroj uživatelem

hlasů
1
string [] temp = new string[] {"1","2","3"};
List<string> temp2 = temp.ToList();
Odpovězeno 21/01/2009 v 22:05
zdroj uživatelem

hlasů
4

Chcete-li inicializovat seznamu s n prvky nějakou pevnou hodnotu:

public List<T> InitList<T>(int count, T initValue)
{
  return Enumerable.Repeat(initValue, count).ToList();
}
Odpovězeno 21/01/2009 v 22:24
zdroj uživatelem

hlasů
4

Zdá se, že klade důraz na potřebu polohové spojení s daty, takže nebude asociativní pole bude vhodnější?

Dictionary<int, string> foo = new Dictionary<int, string>();
foo[2] = "string";
Odpovězeno 23/01/2009 v 14:30
zdroj uživatelem

hlasů
81
List<string> L = new List<string> ( new string[10] );
Odpovězeno 10/03/2009 v 21:04
zdroj uživatelem

hlasů
0

Můžete použít LINQ to chytře inicializovat svůj seznam s výchozí hodnotou. (Podobně jako odpověď David B je .)

var defaultStrings = (new int[10]).Select(x => "my value").ToList();

Jít o jeden krok dál a inicializovat každý řetězec s odlišnými hodnotami „řetězec 1“, „řetězec 2“, „řetězec 3“, atd:

int x = 1;
var numberedStrings = (new int[10]).Select(x => "string " + x++).ToList();
Odpovězeno 24/11/2014 v 19:15
zdroj uživatelem

hlasů
2

Vytvořit pole s počtem kusů, které chcete a pak převést pole do seznamu.

int[] fakeArray = new int[10];

List<int> list = fakeArray.ToList();
Odpovězeno 02/09/2016 v 10:54
zdroj uživatelem

hlasů
0

Oznámení o IList: MSDN IList Poznámky : "IList implementace lze rozdělit do tří kategorií:. Read-only, s pevnou velikostí a variabilní velikosti (...) Pokud jde o generické verze tohoto rozhraní, viz. System.Collections.Generic.IList<T>".

IList<T>NOT dědí z IList(ale List<T>dělá realizovat jak IList<T>a IList), ale vždy s proměnnou velikost . Vzhledem k tomu, .NET 4.5, máme také IReadOnlyList<T>, ale pokud vím, není pevné velikosti obecný seznam, který by byl co hledáte.

Odpovězeno 09/11/2016 v 09:27
zdroj uživatelem

hlasů
0

Toto je ukázkový jsem použil pro své jednotky test. Vytvořil jsem seznam třídy objektu. Pak jsem použil forloop přidat číslo ‚x‘ objektů, které jsem očekávají od služby. Tímto způsobem můžete přidat / inicializovat seznam pro jakoukoliv danou velikost.

public void TestMethod1()
    {
        var expected = new List<DotaViewer.Interface.DotaHero>();
        for (int i = 0; i < 22; i++)//You add empty initialization here
        {
            var temp = new DotaViewer.Interface.DotaHero();
            expected.Add(temp);
        }
        var nw = new DotaHeroCsvService();
        var items = nw.GetHero();

        CollectionAssert.AreEqual(expected,items);


    }

Doufat, že jsem o pomoc na vás.

Odpovězeno 20/11/2016 v 15:48
zdroj uživatelem

hlasů
0

Trochu pozdě, ale první řešení, které navrhl zdá mnohem čistší ke mně nechcete dvakrát alokovat paměť. Dokonce Seznam constrcutor musí procházet pole, aby jej kopírovat; to není ani vědět předem, je tam jen null prvky uvnitř.

1. - přidělit N - smyčky N náklady: 1 * přidělit (N) + N * loop_iteration

2. - přidělit N - přidělit N + smyčka () Cena: 2 * přidělit (N) + N * loop_iteration

Nicméně List příděl an smyčky může být rychlejší, protože seznam je vestavěný ve třídě, ale C # je JIT zkompilovaný tááák ...

Odpovězeno 30/11/2016 v 01:09
zdroj uživatelem

hlasů
1

Akceptovanou odpověď (ten se zeleným háčkem) má problém.

Problém:

var result = Lists.Repeated(new MyType(), sizeOfList);
// each item in the list references the same MyType() object
// if you edit item 1 in the list, you are also editing item 2 in the list

Doporučuji změnu řádek výše provést kopii objektu. Existuje mnoho různých článků o tom:

Chcete-li inicializovat každou položku v seznamu s výchozí konstruktor, spíše než NULL, přidejte následující metodu:

public static List<T> RepeatedDefaultInstance<T>(int count)
    {
        List<T> ret = new List<T>(count);
        for (var i = 0; i < count; i++)
        {
            ret.Add((T)Activator.CreateInstance(typeof(T)));
        }
        return ret;
    }
Odpovězeno 25/07/2019 v 17:52
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more