Yksi asia, jota en koskaan voinut kietoa pääni ympärille, on se, miten Flatten
toimii, kun toimitetaan matriisina toisena argumenttina, ja Mathematica -ohje ei ole erityisen hyvä tässä.
Otettu kohteesta Flatten
Mathematica -dokumentaatio:
Flatten[list, {{s11, s12, ...}, {s21, s22, ...}, ...}]
Tasoittaa
list
yhdistämällä kaikki tasot $ s_ {ij} $, jotta jokaisesta tasosta muodostuu tulos. $”62665b34cf”>
Voisiko joku kertoa tarkemmin, mitä tämä todella tarkoittaa / tarkoittaa?
Vastaa
Yksi kätevä tapa ajatella Flatten
toisella argumentilla on se, että se suorittaa jotain Transpose
-tapaa repaleille (epäsäännöllisille) luetteloille. Tässä on yksinkertainen esimerkki:
In[63]:= Flatten[{{1,2,3},{4,5},{6,7},{8,9,10}},{{2},{1}}] Out[63]= {{1,4,6,8},{2,5,7,9},{3,10}}
Tapahtuu, että elementit muodostavat Alkuperäisen luettelon uted-taso 1
ovat nyt komponentteja tasolla 2
tuloksessa ja päinvastoin. Tätä Transpose
tekee, mutta epäsäännöllisille luetteloille. Huomaa kuitenkin, että osa sijainneista häviää täällä, joten emme voi suoraan kääntää operaatiota:
In[65]:= Flatten[{{1,4,6,8},{2,5,7,9},{3,10}},{{2},{1}}] Out[65]= {{1,2,3},{4,5,10},{6,7},{8,9}}
Jotta se voidaan kääntää oikein, meillä on tehdä jotain tällaista:
In[67]:= Flatten/@Flatten[{{1,4,6,8},{2,5,7,9},{3,{},{},10}},{{2},{1}}] Out[67]= {{1,2,3},{4,5},{6,7},{8,9,10}}
Mielenkiintoisempi esimerkki on, kun pesimme syvemmällä:
In[68]:= Flatten[{{{1,2,3},{4,5}},{{6,7},{8,9,10}}},{{2},{1},{3}}] Out[68]= {{{1,2,3},{6,7}},{{4,5},{8,9,10}}}
Tässä voimme jälleen nähdä, että Flatten
toimi tehokkaasti kuten (yleistetty) Transpose
, vaihtamalla kappaleita kahdella ensimmäisellä tasolla Seuraavaa on vaikeampaa ymmärtää:
In[69]:= Flatten[{{{1, 2, 3}, {4, 5}}, {{6, 7}, {8, 9, 10}}}, {{3}, {1}, {2}}] Out[69]= {{{1, 4}, {6, 8}}, {{2, 5}, {7, 9}}, {{3}, {10}}}
Seuraava kuva kuvaa tätä yleistettyä siirtoa:
Voimme tehdä sen kahdessa peräkkäisessä vaiheessa:
In[72]:= step1 = Flatten[{{{1,2,3},{4,5}},{{6,7},{8,9,10}}},{{1},{3},{2}}] Out[72]= {{{1,4},{2,5},{3}},{{6,8},{7,9},{10}}} In[73]:= step2 = Flatten[step1,{{2},{1},{3}}] Out[73]= {{{1,4},{6,8}},{{2,5},{7,9}},{{3},{10}}}
Koska permutaatio {3,1,2}
voidaan saada nimellä {1,3,2}
ja sen jälkeen {2,1,3}
. Toinen tapa nähdä, miten se toimii, on käytä numeroita wh ich ilmaisee sijainnin luettelorakenteessa:
Flatten[{{{111, 112, 113}, {121, 122}}, {{211, 212}, {221, 222, 223}}}, {{3}, {1}, {2}}] (* ==> {{{111, 121}, {211, 221}}, {{112, 122}, {212, 222}}, {{113}, {223}}} *)
Tästä voidaan nähdä, että syrjäisimmässä luettelossa (ensimmäinen taso), kolmas hakemisto (vastaa alkuperäisen luettelon kolmas taso) kasvaa, jokaisessa jäsenluettelossa (toinen taso) ensimmäinen elementti kasvaa elementtiä kohti (vastaa alkuperäisen luettelon ensimmäistä tasoa) ja lopuksi sisimmissä (kolmas taso) luetteloissa toinen indeksi kasvaa , joka vastaa alkuperäisen luettelon toista tasoa. Yleensä jos toisena elementtinä läpäistyn luettelon k: s elementti on {n}
, k: nnen indeksin kasvattaminen tuloksena olevassa luettelorakenteessa vastaa n: nnen indeksin kasvua alkuperäinen rakenne.
Lopuksi voidaan yhdistää useita tasoja tasoittamaan alatasoja tehokkaasti, kuten näin:
In[74]:= Flatten[{{{1,2,3},{4,5}},{{6,7},{8,9,10}}},{{2},{1,3}}] Out[74]= {{1,2,3,6,7},{4,5,8,9,10}}
Kommentit
vastaus
Toinen luetteloargumentti ryhmälle Flatten
palvelee kahta tarkoituksiin. Ensinnäkin se määrittää järjestyksen, jossa indeksit toistetaan elementtejä kerättäessä. Toiseksi se kuvaa luettelon litistämistä lopputuloksessa. Tarkastellaan kutakin näistä ominaisuuksista vuorotellen.
Kordausjärjestys
Harkitse seuraavaa matriisia:
$m = Array[Subscript[m, Row[{##}]]&, {4, 3, 2}]; $m // MatrixForm
Voimme käyttää Table
-lausekkeen avulla voit luoda kopion matriisista iteroimalla kaikki sen elementit:
$m === Table[$m[[i, j, k]], {i, 1, 4}, {j, 1, 3}, {k, 1, 2}] (* True *)
Tämä identiteetti toiminta ei ole mielenkiintoista, mutta voimme muuttaa taulukon vaihtamalla iteraatiomuuttujien järjestyksen. Esimerkiksi voimme vaihtaa i
ja j
iteraattorit. Tämä tarkoittaa tason 1 ja 2 indeksien ja niitä vastaavien elementtien vaihtamista:
$r = Table[$m[[i, j, k]], {j, 1, 3}, {i, 1, 4}, {k, 1, 2}]; $r // MatrixForm
Jos katsomme tarkkaan, voimme nähdä, että jokaisen alkuperäisen elementin $m[[i, j, k]]
havaitaan vastaavan syntynyttä elementtiä $r[[j, i, k]]
– kahdella ensimmäisellä indeksillä on mehiläinen n ”vaihdettu”.
Flatten
antaa meille mahdollisuuden ilmaista vastaavampi operaatio tälle lausekkeelle Table
:
$r === Flatten[$m, {{2}, {1}, {3}}] (* True *)
Lausekkeen Flatten
toinen argumentti määrittää nimenomaisesti halutun hakemistojärjestyksen: indeksit 1, 2, 3 ovat muutettu indeksiksi 2, 1, 3. Huomaa, kuinka meidän ei tarvinnut määrittää aluetta taulukon kullekin ulottuvuudelle – merkittävä notaatiomukavuus.
Seuraava Flatten
on identiteettitoiminto, koska siinä ei määritetä muutoksia hakemistojärjestykseen:
$m === Flatten[$m, {{1}, {2}, {3}}] (* True *)
Seuraava lauseke järjestää kaikki kolme indeksiä uudelleen: 1, 2 , 3 -> 3, 2, 1
Flatten[$m, {{3}, {2}, {1}}] // MatrixForm
Jälleen , voimme varmistaa, että hakemistosta [[i, j, k]]
löydetty alkuperäinen elementti löytyy nyt tuloksesta osoitteesta [[k, j, i]]
.
Jos Flatten
lauseketta, niitä kohdellaan ikään kuin ne olisi määritelty viimeisenä ja luonnollisessa järjestyksessä:
Flatten[$m, {{3}}] === Flatten[$m, {{3}, {1}, {2}}] (* True *)
Tämä viimeinen esimerkki voi lyhennetään vielä tarkemmin:
Flatten[$m, {3}] === Flatten[$m, {{3}}] (* True *)
Tyhjä hakemistoluettelo johtaa identiteettioperaatioon:
$m === Flatten[$m, {}] === Flatten[$m, {1}] === Flatten[$m, {{1}, {2}, {3}}] (* True *)
Se huolehtii iterointijärjestyksestä ja indeksinvaihdosta. Katsotaan nyt seuraavaa …
Luettelon litistäminen
Saattaa ihmetellä, miksi meidän oli määritettävä kukin hakemisto alaluettelosta edellisissä esimerkeissä. Syynä on se, että kukin hakemistomäärittelyn alaluettelo määrittää, mitkä indeksit on tasoitettava yhteen tuloksessa. Harkitse uudelleen seuraavaa identiteettioperaatiota:
Flatten[$m, {{1}, {2}, {3}}] // MatrixForm
Mitä tapahtuu, jos yhdistämme kaksi ensimmäistä indeksiä samaan aliluetteloon ?
Flatten[$m, {{1, 2}, {3}}] // MatrixForm
Voimme nähdä, että alkuperäinen tulos oli 4 x 3 pariruudukko, mutta toinen tulos on yksinkertainen luettelo pareista. Syvin rakenne, parit, jätettiin koskematta. Kaksi ensimmäistä tasoa on litistetty yhdeksi tasoksi. Lähteen kolmannen tason parit matriisi pysyi litistämättömänä.
Voisimme yhdistää sen sijaan kaksi toista indeksiä:
Flatten[$m, {{1}, {2, 3}}] // MatrixForm
Tällä tuloksella on sama määrä rivejä kuin alkuperäisellä matriisilla, mikä tarkoittaa, että ensimmäinen taso jätettiin koskematta. Mutta jokaisella tulosrivillä on tasainen luettelo kuudesta elementistä, jotka on otettu vastaavasta alkuperäisestä kolmen parin rivistä. Siksi kaksi alinta tasoa on litistetty.
Voimme myös yhdistää kaikki kolme indeksiä saadaksesi täysin litistyneen tuloksen:
Flatten[$m, {{1, 2, 3}}]
Tämä voidaan lyhentää:
Flatten[$m, {{1, 2, 3}}] === Flatten[$m, {1, 2, 3}] === Flatten[$m] (* True *)
Flatten
tarjoaa myös lyhenteen merkinnän, kun hakemistonvaihtoa ei tapahdu:
$n = Array[n[##]&, {2, 2, 2, 2, 2}]; Flatten[$n, {{1}, {2}, {3}, {4}, {5}}] === Flatten[$n, 0] (* True *) Flatten[$n, {{1, 2}, {3}, {4}, {5}}] === Flatten[$n, 1] (* True *) Flatten[$n, {{1, 2, 3}, {4}, {5}}] === Flatten[$n, 2] (* True *) Flatten[$n, {{1, 2, 3, 4}, {5}}] === Flatten[$n, 3] (* True *)
”Ragged” -taulukot
Kaikissa tähänastisissa esimerkeissä on käytetty eri ulottuvuuksien matriiseja. Flatten
tarjoaa erittäin tehokkaan ominaisuuden, joka tekee siitä muutakin kuin lyhenteen Table
-lausekkeesta. Flatten
käsittelee sulavasti tapausta, jossa tietyn tason alaluetteloiden pituus on erilainen. Puuttuvat elementit ohitetaan hiljaa. Esimerkiksi kolmion muotoinen taulukko voidaan kääntää:
$t = Array[# Range[#]&, {5}]; $t // TableForm (* 1 2 4 3 6 9 4 8 12 16 5 10 15 20 25 *) Flatten[$t, {{2}, {1}}] // TableForm (* 1 2 3 4 5 4 6 8 10 9 12 15 16 20 25 *)
…tai käännetty ja litistetty:
Flatten[$t, {{2, 1}}] (* {1,2,3,4,5,4,6,8,10,9,12,15,16,20,25} *)
kommentit
- Tämä on upea ja perusteellinen selitys!
- @ rm-rf Kiitos. Luulen, että jos
Flatten
yleistettäisiin hyväksymään funktio, jota sovellettaisiin indeksejä litistettäessä, se olisi erinomainen alku ” tensori-algebra tölkissä ”. - Joskus meidän on tehtävä sisäisiä supistuksia. Nyt tiedän, että voin tehdä sen käyttämällä
Flatten[$m, {{1}, {2, 3}}]
-toimintoa Map Flatten -toiminnon sijaan jollain tasolla. Olisi mukavaa, josFlatten
hyväksyisi negatiiviset argumentit. Joten tämä tapaus voidaan kirjoittaa kutenFlatten[$m, -2]
. - Miksi tämä erinomainen vastaus sai vähemmän ääniä kuin Leonid ’ s: (.
- @Tangshutao Katso toinen UKK-profiili -profiilissani .
Vastaus
Olen oppinut paljon WReachin ja Leonidin vastauksista ja haluaisin antaa pienen panoksen:
Vaikuttaa arvoiselta korostamalla, että luetteloarvoisen Flatten
-argumentin ensisijainen tarkoitus on vain tasoittaa tiettyjä luettelotasoja (kuten WReach mainitsee Luettelon litistäminen -osio). Flatten
: n käyttäminen räikeänä Transpose
näyttää puolelta mielestäni tämän ensisijaisen suunnittelun vaikutus.
Esimerkiksi eilen minun piti muuttaa tätä luetteloa
lists = { {{{1, 0}, {1, 1}}, {{2, 0}, {2, 4}}, {{3, 0}}}, {{{1, 2}, {1, 3}}, {{2, Sqrt[2]}}, {{3, 4}}} (*, more lists... *) };
tähän:
list2 = { {{1, 0}, {1, 1}, {2, 0}, {2, 4}, {3, 0}}, {{1, 2}, {1, 3}, {2, Sqrt[2]}, {3, 4}} (*, more lists... *) }
Eli minun täytyi murskata toinen ja kolmas luettelotaso yhteen.
Tein sen
list2 = Flatten[lists, {{1}, {2, 3}}];
vastaus
Tämä on vanha kysymys, mutta usein kysyy erä ihmisiä. Tänään, kun yritin selittää, miten tämä toimii, törmäsin melko selkeään selitykseen, joten mielestäni sen jakamisesta täällä olisi hyötyä uudelle yleisölle.
Mitä indeksi tarkoittaa?
Anna ensin selventää mikä index on: Mathematicassa jokainen lauseke on puu, esimerkiksi luettelossa:
TreeForm@{{1,2},{3,4}}
Kuinka navigoit puussa?
Yksinkertainen! Aloitat juuresta ja valitset jokaisella risteyksellä, minkä tien mennä, esimerkiksi täällä, jos haluat päästä 2
, aloitat valitsemalla ensimmäinen polku ja valitse sitten toinen polku. Kirjoitetaan ”s” se nimellä {1,2}
, joka on vain lausekkeen elementti 2
tässä lausekkeessa.
Kuinka ymmärtää Flatten
?
Harkitse tässä yksinkertaista kysymystä, jos en anna sinulle täydellistä lauseketta, mutta sen sijaan annan sinulle kaikki elementit ja heidän hakemistonsa, miten rakennat alkuperäisen lausekkeen? Esimerkiksi tässä annan sinulle:
{<|"index" -> {1, 1}, "value" -> 1|>, <|"index" -> {1, 2}, "value" -> 2|>, <|"index" -> {2, 1}, "value" -> 3|>, <|"index" -> {2, 2}, "value" -> 4|>}
ja sanon, että kaikki päät ovat List
, niin mitä ”s alkuperäinen lauseke?
No, varmasti voit rekonstruoida alkuperäisen lausekkeen nimellä {{1,2},{3,4}}
, mutta miten? Luultavasti voit luetella seuraavat vaiheet:
- Tarkastellaan ensin indeksin ensimmäistä elementtiä ja lajitellaan ja kerätään sen mukaan. Sitten tiedämme, että ensimmäinen koko lausekkeen elementin tulisi sisältää kaksi ensimmäistä -elementtiä alkuperäisessä luettelossa …
- Sitten jatkamme toisen argumentin tarkastelua, tee sama …
- Lopuksi saamme alkuperäisen luettelon nimellä
{{1,2},{3,4}}
.
No, se on järkevää! Joten mitä jos sanon sinulle, ei, sinun pitäisi ensin lajitella ja kerätä indeksin toisen elementin mukaan ja sitten kerätä indeksin ensimmäisen elementin mukaan? Tai sanon, että emme kerää niitä kahdesti, me vain lajittelemme molemmat elementit, mutta annamme ensimmäiselle argumentille korkeamman prioriteetin?
No, saatat todennäköisesti saada seuraavat kaksi luetteloa, eikö?
-
{{1,3},{2,4}}
-
{1,2,3,4}
No, tarkista itse, Flatten[{{1,2},{3,4}},{{2},{1}}]
ja Flatten[{{1,2},{3,4}},{{1,2}}]
tee sama!
Joten ymmärrät Flattenin toisen argumentin ?
- Jokainen pääluettelon sisältämä luetteloelementti, esimerkiksi
{1,2}
, tarkoittaa, että sinun pitäisi GATHER kaikki luettelot näiden hakemistossa olevien elementtien mukaan, toisin sanoen nämä tasot . - Listaelementin sisäinen järjestys edustaa sitä, miten LAJITTELET edellisessä vaiheessa luetteloon kerätyt elementit . esimerkiksi
{2,1}
tarkoittaa, että toisen tason sijainnilla on korkeampi prioriteetti kuin ensimmäisen tason sijainnilla.
Esimerkkejä
Olkoon nyt jonkin verran käytäntöä tuntemaan aiemmat säännöt.
1. Transpose
Transpose
yksinkertaisella m * n -matriisilla on tehdä $ A_ {i, j} \ rightarrow A ^ T_ {j, i} $. Mutta voimme pitää sitä toisella tavalla, alun perin lajittelemme elementti i
-hakemistonsa mukaan ja lajitellaan ensin niiden j
-hakemiston mukaan, nyt meidän on muutettava vain lajittelemaan ne j
indeksoi ensin ja sitten i
seuraavaksi! Koodista tulee siis:
Flatten[mat,{{2},{1}}]
Yksinkertainen, eikö?
2. Perinteinen Flatten
Perinteisen litistämisen tavoite yksinkertaisella m * n -matriisilla on luo 1D-matriisi 2D-matriisin sijaan, esimerkiksi: Flatten[{{1,2},{3,4}}]
palauttaa {1,2,3,4}
. Tämä tarkoittaa, että emme tällä kertaa ”t kerää -elementtejä, vain lajittele ne ensin ensimmäisen hakemistonsa ja sitten toisen mukaan:
Flatten[mat,{{1,2}}]
3. ArrayFlatten
Tarkastellaan yksinkertaista ArrayFlatten-tapausta, tässä on 4D-luettelo:
{{{{1,2},{5,6}},{{3,4},{7,8}}},{{{9,10},{13,14}},{{11,12},{15,16}}}}
niin miten voimme tehdä tällaisen muunnoksen, jotta siitä tulisi 2D-luettelo?
$ \ left (\ begin {array} {cc} \ left (\ begin {array} {cc} 1 & 2 \\ 5 & 6 \\ \ end {array} \ right) & \ vasen (\ begin {array} {cc} 3 & 4 \\ 7 & 8 \\ \ end {array} \ right) \\ \ left (\ begin {array} {cc} 9 & 10 \\ 13 & 14 \\ \ end {array} \ oikea) & \ left (\ begin {array} {cc} 11 & 12 \\ 15 & 16 \\ \ end {array} \ right) \\ \ end {array} \ right) \ rightarrow \ left (\ begin {array} {cccc} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 10 & 11 & 12 \\ 13 & 14 & 15 & 16 \\ \ end {array} \ right) $
No, tämä on myös yksinkertaista, tarvitsemme ensin ryhmän alkuperäisen ensimmäisen ja kolmannen tason indeksin mukaan, ja meidän pitäisi antaa ensimmäiselle indeksille korkeampi prioriteetti lajittelu. Sama pätee toiseen ja neljänteen tasoon:
Flatten[mat,{{1,3},{2,4}}]
4. ”Muuta kuvan kokoa”
Nyt meillä on kuva, esimerkiksi:
img=Image@RandomReal[1,{10,10}]
Mutta se on ehdottomasti liian pieni, jotta voimme näkymää, joten haluamme tehdä siitä suuremman laajentamalla jokaisen pikselin 10 * 10 -kokoiseksi valtavaksi pikseliksi.
Yritämme ensin:
ConstantArray[ImageData@img,{10,10}]
Mutta se palauttaa 4D-matriisin, jonka mitat ovat {10,10,10,10}. Meidän pitäisi siis Flatten
se. Tällä kertaa haluamme kolmannen argumentin olevan korkeampi prioriteetti ensimmäisestä, joten pieni viritys toimisi:
Image@Flatten[ConstantArray[ImageData@img,{10,10}],{{3,1},{4,2}}]
Vertailu:
Toivottavasti tämä voi auttaa!
Flatten[{{{111, 112, 113}, {121, 122}}, {{211, 212}, {{221,222,223}}}, {{3},{1},{2}}}
ja tulos olisi{{{111, 121}, {211, 221}}, {{112, 122}, {212, 222}}, {{113}, {223}}}
.In[63]:= Flatten[{{1,2,3},{4,5},{6,7},{8,9,10}},{{2},{1}}] Out[63]= {{1,4,6,8},{2,5,7,9},{3,10}}
-sivustolle sanot Mitä tapahtuu, elementit, jotka olivat alkuperäisen luettelon tason 1, ovat nyt komponentteja tason 2 tulos. En ’ ymmärrä oikein, syötteillä ja tuotoksilla on sama tasorakenne, elementit ovat edelleen samalla tasolla.Voitteko selittää tämän yleisesti?