I helgen bestämde jag mig för att försöka min hand i Scala och Clojure. Jag är skicklig med objektorienterad programmering, och så var Scala lätt att hämta som ett språk, men ville prova funktionell programmering. Det här var det svårt. Jag kan bara t verkar få mitt huvud till ett sätt att skriva funktioner Som en expertfunktionell programmerare, hur kommer du till ett problem. Ge en lista med värden och en definierad summationstid, hur skulle du skapa en ny lista med det enkla glidande medlet av listan. För exempel Med tanke på listvärdena 2 0, 4 0, 7 0, 6 0, 3 0, 8 0, 12 0, 9 0, 4 0, 1 0 och perioden 4, bör funktionen returnera 0 0 , 0, 0 0, 4 75, 5 0, 6 0, 7 25, 8 0, 8 25, 6 5. Efter att ha spenderat en dag på att mulla över det var det bästa jag kunde komma med i Scala detta. Jag vet Det här är fruktansvärt ineffektivt, jag vill hellre göra något liknande. Nu skulle det enkelt bli gjort i en tvingande stil, men jag kan för mig avgöra hur man uttrycker det funktionellt. Intressant problem jag kan tänka på ma ny lösningar med varierande grad av effektivitet Att behöva lägga till saker upprepade gånger är inte ett prestanda problem, men låt oss anta att det också kan nollorna i början läggas på senare, så låt oss inte oroa sig för att producera dem. Om algoritmen ger De är naturligtvis bra, om inte, vi korrigerar det senare. Börja med Scala 2 8, skulle följande ge resultatet för n period genom att använda glidning för att få ett glidfönster i listan. Trots att det här är ganska elegant, gör det inte har bästa möjliga prestanda, eftersom det inte utnyttjar redan beräknade tillägg. Så talar vi om dem, hur kan vi få dem. Låt oss säga att vi skriver detta. Vi har en lista över summan av varje par. Låt oss försöka använd detta resultat för att beräkna det rörliga genomsnittet av 4 element. Ovanstående formel gjorde följande beräkning. Så om vi tar varje element och lägger till det andra nästa elementet får vi det glidande medlet för 4 element. Vi kan göra det så här. Vi kunde då beräkna det rörliga genomsnittet För 8 element och så vidare Tja, det finns en välkänd algoritm för att beräkna saker som följer ett sådant mönster Det är mest känt för dess användning vid beräkning av kraften i ett nummer Det går så här. Så, låt oss tillämpa det här. Så , Här är logikperioden 0 ogiltig, period 1 är lika med ingången, period 2 är glidningsfönstret av storlek 2 Om det är större än så kan det vara jämnt eller udda. Om det är konstigt lägger vi till varje element i rörelsens Nästa udda - 1 element Till exempel, om 3 lägger vi till varje element i movingSum av de följande 2 elementen. Om vi beräknar det movingSum för n 2 lägger vi sedan till varje element i ett n 2 steg efteråt. Med den här definitionen, Vi kan sedan gå tillbaka till problemet och göra det. Det är en liten ineffektivitet med avseende på användningen av men det är o period, inte Det kan bli effektivare med en rekursiv funktion i svansen Och såklart är definitionen av glidning I Förutsatt att det är skrämmande prestationsvis, men det kommer att bli en mycket bättre definition av det på Scala 2 8 Observera att vi inte kan göra en Effektiv glidmetod på en lista men vi kan göra det på en Iterable. Having sagt allt det, jag går med den allra första definitionen och optimerar bara om en kritisk sökväg analyserade detta som en stor sak. Till avsluta, låt oss överväga hur jag gick om problemet Vi har ett glidande medelvärde Ett glidande medelvärde är summan av ett rörligt fönster på en lista, dividerat med storleken på det här fönstret Så först försöker jag få ett glidande fönster, summa allt på det, Och sedan dela med sig av storleken. Nästa problem var att undvika repetition av redan beräknade tillägg. I det här fallet gick jag till det minsta möjliga tillägget och försökte räkna ut hur man beräknar större summor om att använda sådana resultat. Slutligen, försök att Lösa problemet som du tänkte på det genom att lägga till och subtrahera från föregående resultat. Få det första genomsnittet är enkelt. Nu gör vi två listor Först, listan över element som ska subtraheras. Nästa, listan över element som ska läggas till. Vi kan Lägg till dessa två listor med hjälp av zip. Denna metod kommer endast att producera Uce så många element som den mindre listan har, vilket undviker att problemet att subtraheras är större än nödvändigt. Vi avslutar genom att komponera resultatet med en vik. Vilket är svaret som ska returneras Hela funktionen ser ut så här. Jag vet Clojure bättre än Scala, så här går När jag skriver detta är den andra Clojure-posten här absolut nödvändigt att det inte är riktigt vad du återvänder och inte är idiomatisk Clojure Den första algoritmen som kommer till mitt hjärta är upprepade gånger att ta det önskade antalet element från sekvensen, släppa det första elementet och återkommande. Följande fungerar på någon form av sekvensvektor eller lista, lat eller inte och ger en lat sekvens av medelvärden --- vilket kan vara till hjälp om du arbetar på en lista med obestämd storlek Observera att det tar vård av basfallet genom att implicit returnera noll om det inte finns tillräckligt med element i listan att konsumera. Kör detta på dina testdata. Det ger inte 0 för de första elementen i sekvensen, men det kan lätt hanteras lite Vad artificially. The easiest sak av allt är att se mönstret och kunna komma ihåg en tillgänglig funktion som passar billpartitionen ger en lat vy över delar av en sekvens, som vi då kan kartlägga. Någon bad om en svans Rekursiv version svans recursion vs latskap är lite av en tradeoff När ditt jobb bygger upp en lista så är det vanligtvis ganska enkelt att göra din funktion svans rekursiv, och det här är inget undantag --- bygga bara upp listan som ett argument till en delfunktion Vi kommer att ackumulera till en vektor istället för en lista eftersom annars listan kommer att byggas upp bakåt och måste vändas i slutet. Loop är ett sätt att göra en anonym inre funktion som, till exempel, Scheme s namnet let recur måste användas I Clojure för att eliminera svanssamtal conj är en generaliserad nackdel som lägger till på det sätt som är naturligt för samlingen --- början av listor och slutet av vektorer. Svarade aug 24 09 vid 2 58. Jag har bestämt mig för att lägga till denna gamla Q, Eftersom ämnet kom upp igen och jag f Det är föredraget att peka på den här fina samlingen av möjliga lösningar samtidigt som jag lägger till en egen tag som skiljer sig från tidigare versioner i Clojure, som förklaras i A. Kanske kan vi bygga webbens mest kompletta arkiv av funktionella mov-avg-implementeringar - Micha Marczyk Mar 2 10 på 0 20.Här sa delvis punktfri en linje Haskell lösning. Första gäller att svansar till listan för att få svans listor, så. Vändar det och släpper de första p-poster som tar p som 2 här. Om du känner inte till symbolen för punktnippel, det är operatören för funktionell komposition, vilket innebär att den överför utgången från en funktion som ingången till en annan, som komponerar dem i en enda funktion gf betyder att run f är ett värde och sedan överför utgången till g , så fgx är densamma som gfx Generellt leder användningen till en tydligare programmeringsstil. Det kartlägger sedan funktionen frånIntegral p sum tar p på listan Så för varje lista i listan tar det de första p-elementen, summerar dem och delar sedan dem av p då vi flipar bara listan igen med omvändt. Det här ser mycket mer ineffektivt ut än det är omvändt, men det går inte att fysiskt vända ordningens lista tills listan är utvärderad. Den lägger bara ut på stapeln. Bra och lata Haskell-svansar Skapar inte alla de separata listorna, det refererar bara till olika delar av originallistan. Det är fortfarande inte en bra lösning, men den är en linje lång. Här är något snyggare men längre lösning som använder MapAccum för att göra en glidande subtraktion och addition. vi delar upp listan i två delar på p, så. Sum den första biten. Tryck den andra biten med den ursprungliga listan. Detta bara parar av objekt i ordning från de två listorna. Den ursprungliga listan är uppenbarligen längre men vi förlorar den extra biten. Nu definierar vi en funktion för vår kartaAccum ulator mapAccumL är samma som karta, men med en extra löpande ackumulatorparameter som går från den föregående mappningen till nästa när kartan går igenom listan Vi använder ackumulatorn som vårt glidande medelvärde , Och eftersom vår lista är formad av det element som just har lämnat glidfönstret och det element som just har skrivit in den listan vi bara har zippat tar vår glidande funktion det första talet x bort från medelvärdet och lägger till det andra talet y Vi då passera de nya s längs och återvända s dividerad med p snd sekund tar bara den andra medlemmen av ett par tupel, som används för att ta det andra returvärdet av mapAccumL, eftersom mapAccumL kommer att returnera ackumulatorn såväl som den mappade listan. För dem av dig som inte är bekant med symbolen är det applikationsoperatören. Det gör inte vad som helst, men det har en låg, höger-associativ bindande företräde, så det betyder att du kan lämna ut parenteserna notera LISPers, iefx är detsamma som f x. Running ma 4 2 0, 4 0, 7 0, 6 0, 3 0, 8 0, 12 0, 9 0, 40, 1 0 ger 4 75, 50, 0, 7 25, 80, 8 25, 6 5 för antingen lösning. Och du måste importera modullistan för att kompilera endera lösningen. Daniel Tack Skriv kod är mycket lättare än att förklara det. Du har beskrivit det här. Två listor Strömmar bibehålls i båda funktionerna och får sina huvuden tagna under varje iteration. En lista Stream fungerar som huvudsamlingen för att iterera igenom medan den andra List Stream, som är samma samling med undantag av period mindre Dubblar som tagits av den, används vid beräkningen av det nya glidande medlet Walter Chang aug 24 09 på 17 19.J programmeringsspråket underlättar program som rörande medelvärde. Det finns faktiskt färre tecken än i deras etikett, glidande medelvärde. För de värden som anges i denna fråga inklusive namnetvärdena här är ett enkelt sätt att koda detta. Vi kan beskriva detta med hjälp av etiketter för komponenter. Båda exempel använder exakt samma program Den enda skillnad är användningen av flera namn i den andra formen. Sådana namn kan hjälpa läsare som inte vet J-primarierna. Låt oss titta lite längre på vad som händer i delprogrammet, medelvärdet d antecknar summation och betecknar division som det klassiska tecknet Beräkning av ett talantal av objekt görs av det övergripande programmet, då är summan av värden dividerat med värdet av värden. Resultatet av den genomsnittliga beräkning som skrivs här inkluderar inte Ledande nollor förväntas i den ursprungliga frågan Dessa nollor är förmodligen inte en del av den avsedda beräkningen. Tekniken som används här kallas tyst programmering. Det är ungefär detsamma som den fria stilen för funktionell programmering. Ansvarig aug 26 10 vid 16 15. Här är Clojure som låtsas vara ett mer funktionellt språk Det här är helt svansrekursivt, btw och innehåller ledande nollor. Jag sätter ihop samlings - eller listparametern senast för att göra funktionen lättare att curry Men i Clojure. is är det så besvärligt att jag brukar sluta göra detta. I vilket fall spelar det ingen roll vilken ordning parametrarna går. Svarade aug 24 09 på 4 56. Han Jonathan, jag är ganska ny på denna funktionella programmering, kan du tacka för mig hur är är rekursivt Tack James P Aug 24 09 vid 14 38. Rekursionen händer på if-satsen, där antingen alternativet är baserat på återkommande. Detta kommer att beräkna varje parameter först och endast sedan recurse. Svaret kommer att bli resultatet av återkommande As Resultatet är det samma resultatet som återkommer av rekursionen, utan några andra beräkningar, det här är rekursivt svans Daniel C Sobral Aug 24 09 på 15 20.Detta exempel använder sig av staten, eftersom det är en pragmatisk lösning i detta fall och en stängning för att skapa windowing-medelvärdet funktion. Det är fortfarande funktionellt i den meningen att använda förstklassiga funktioner, även om det inte är biverkningsfritt. De två språk som du nämnde båda körs ovanpå JVM och därmed båda tillåter tillstånds - Ledning när det behövs. Svarade aug 24 09 på 1 55. Den här lösningen är i Haskell, vilket är mer bekant för mig. Svarade aug 24 09 på 10 23. Jag gillar att använda matchmeddelandet försökte göra något liknande men kunde inte Gör det hela vägen där James P Aug 24 09 at 14 39. En kort Clojure-version som har fördelen att vara O-listlängd oavsett din period. Detta utnyttjar det faktum att du kan beräkna summan av ett antal tal genom att skapa en kumulativ summa av sekvensen t. ex. 1 2 3 4 5 - 0 1 3 6 10 15 och sedan subtrahera de två siffrorna med en förskjutning som är lika med din period. När jag kom sent på festen och ny till funktionell programmering kom jag till denna lösning med en inre funktion. Jag antog idén att Dela upp hela listan med tiden i förväg Då genererar jag summan som börjar med de första elementen och jag genererar de första og ogiltiga elementen 0 0, 0 0. Sedan rekursivt rekryterar jag det första och lägger till det sista värdet I slutet listar jag hela saken. ansvarad den 29 april 10 på 19 28. I Haskell pseudokod. Nu borde man verkligen abstrahera 4 out. answered 23 juli 13 på 13 45. Nyckeln är svansfunktionen, som kartlägger en lista på en lista med kopior av ursprungslistan med egenskapen att n: e elementet i resultatet Saknar de första n-1 elementen. Vi tillämpar fmap avg ta n till resultatet, vilket innebär att vi tar prefixet från n längd från dellistan och beräknar dess avg Om längden på listan vi är avg ing inte n, Då beräknar vi inte genomsnittet eftersom det är odefinierat. Då returnerar vi ingenting. Om det är gör vi det och slår det in. Bara Slutligen kör vi catMaybes på resultatet av fmap avg take n, för att bli av med kanske Type. answered 21 okt 13 på 1 29. Jag blev förvånad över och uppskattad av resultatet av vad som tycktes mig vara de mest idiomatiska Clojure-lösningarna, JamesCunninghams lata-seq-lösningar. Så här är en kombination av James-lösningen med s idé om att anpassa snabb - exponentiation till rörliga summor. Ändra den här baserade på mikas s-lösning - är ännu snabbare. svarat 22 juli kl 13 på 19 21. Din Svar.2017 Stack Exchange, Inc. Införd i Spark 1 4 förbättrade Spark-fönsterfunktionerna uttryck för Spark DataFrames och Spark SQL Med fönsterfunktioner kan du enkelt beräkna ett glidande medelvärde eller kumulativ summa eller referensvärde i en föregående rad av Ett bord Fönsterfunktioner gör att du kan göra många vanliga beräkningar med DataFrames, utan att behöva tillgripa RDD-manipulation. Sammanställningar, UDF-versioner jämfört med Window-funktioner. Windowfunktionerna kompletterar befintliga DataFrame-operationsaggregat, som summa och avg och UDF. För att se över aggregat beräkna ett resultat, en summa eller ett medelvärde för varje grupp av rader medan UDF: erna beräknar ett resultat för varje rad baserat på enbart data i den raden. I kontrast räknar fönsterfunktionerna ett resultat för varje rad baserat på ett raderfönster. Till exempel, I ett glidande medelvärde beräknar du för varje rad medeltalet av raderna som omger den aktuella raden, det här kan göras med fönstervfunktioner. Flyttande medelexempel. Låt oss dyka direkt in i m I genomsnitt exemplet I det här exempeldatasetet finns det två kunder som har spenderat olika mängder pengar varje dag. Bygga kunden DataFrame Alla exempel är skrivna i Scala med Spark 1 6 1, men detsamma kan göras i Python eller SQL. val kunder 2016-05-01, 50 00. Alice, 2016-05-03, 45 00. Alice , 2016-05-04, 55 00. Bob, 2016-05-01, 25 00.Window-funktionen och Window Spec-definitionen. Som visas i det ovanstående exemplet finns det två delar för att tillämpa en fönsterfunktion 1 som anger fönsterfunktionen, Såsom avg i exemplet och 2 som anger fönsterspecifikationen eller wSpec1 i exemplet För 1, kan du hitta en fullständig lista över fönstervärdena här. Du kan använda funktioner som anges under Aggregate Functions och Window Functions. For 2 anger ett fönster Spec, det finns tre komponenter partition av, order av och frame. Partition genom att definiera hur data grupperas i ovanstående exempel, det var av kunden Du måste ange en rimlig gruppering eftersom alla data inom en grupp kommer att samlas in till samma maskin Idealiskt har DataFrame redan delats av önskad gruppering. Order by definierar hur rader ordnas inom en grupp i det ovanstående exemplet, det var efter datum. Frame definierar gränserna för fönstret i förhållande till den aktuella raden i exemplet ovan, fönstret varierade mellan föregående rad och nästa ro. Cumulative Sum. Next, låt oss beräkna den kumulativa summan av det använda beloppet per kund. Fönstret specificerar ramen varierar från början till den aktuella raden 0.val wSpec2 0. Skapa en ny kolumn som beräknar summan över den definierade fönstret. Genomsnittet Enkelt glidande medelvärde. Genomsnittet Enkelt glidande medelvärde Du uppmanas att lösa uppgiften enligt Uppgiftsbeskrivningen, med vilket språk som helst, kan du känna till det enkla glidande medlet av en serie tal. Skapa en stateful-funktionsklass förekomst som tar en period och returnerar en rutin som tar ett tal som argument och ger ett enkelt glidande medelvärde av dess argument så Långt. Ett enkelt glidande medelvärde är en metod för att beräkna ett medelvärde av en ström av siffror genom att endast beräkna de sista P-talen från strömmen, där P är känd som perioden. Det kan implementeras genom att anropa en initialiseringsrutin med P som dess argument, IP, som då ska returnera en rutin som när den kallas med enskilda, successiva medlemmar i en ström av siffror, beräknar medelvärdet av upp till, den sista P av dem, kan kalla detta SMA. Ordet s Tateful i uppgiftsbeskrivningen hänvisar till behovet av att SMA ska komma ihåg viss information mellan samtal till den. Perioden, P. An beställde behållare av åtminstone de sista P-talen från var och en av sina enskilda samtal. Statlig betyder också att på varandra följande samtal till I , Bör initieraren returnera separata rutiner som inte delar sparat tillstånd så att de kan användas på två oberoende dataströmmar. Pseudo-kod för en implementering av SMA är. Den här versionen använder en ihållande kö för att hålla de senaste p-värdena Varje Funktionen som returneras från init-moving-genomsnittet har sitt tillstånd i en atom som håller ett kövärde. Denna implementering använder en cirkellista för att lagra siffrorna i fönstret i början av varje iterationspekare hänvisar till listcellen som håller värdet bara i rörelse Ut ur fönstret och ersättas med det just-added value. Using en Closure edit. Currently den här sma kan inte vara nogc eftersom den allokerar en stängning på högen Några escape analys kan ta bort heap allokeringen. Använda en strukturredigering. Denna version undviker hålfördelningen av förslutningen och håller data i stapelramen för huvudfunktionen Samma utmatning. För att undvika att de flytande punkts approximationerna fortsätter att växa upp och växer kan koden utföra en periodisk summa på helheten circular queue array. This implementation producerar två funktionsobjekt delningstillstånd Det är idiomatiskt i E för att separera inmatning från utgången läs från skriv istället för att kombinera dem i ett objekt. Strukturen är densamma som genomförandet av Standardavvikelse E. Elixirprogrammet nedan Genererar en anonym funktion med en inbäddad period p, som används som perioden för det enkla glidande medlet. Körningsfunktionen läser numerisk ingång och skickar den till den nyupprettade anonyma funktionen och inspekterar sedan resultatet till STDOUT. Utsignalen visas nedan , med medelvärdet, följt av den grupperade ingången, som utgör grunden för varje glidande medelvärde. Längre har stängningar men oföränderliga variabler En lösning är då att använda process Ses och ett enkelt meddelande som passerar baserade API. Matrix-språk har rutiner för att beräkna glidningsavvikelserna för en given sekvens av objekt. Det är mindre effektivt att slinga som i följande kommandon. Kontinuerligt uppmanar till en ingång I som läggs till i slutet av En lista L1 L1 kan hittas genom att trycka på 2ND 1 och medelvärden finns i List OPS. Press ON för att avsluta programmet. Function som returnerar en lista som innehåller den genomsnittliga data för det medföljande argumentet. Program som returnerar ett enkelt värde vid varje Invocation. list är listan som är genomsnittlig p är perioden 5 återvänder den genomsnittliga listan. Exempel 2 Använda programmet movinav2 i, 5 - Initiera glidande medelberäkningen och definiera perioden 5 movinav2 3, xx - nya data i listvärdet 3 , Och resultatet lagras på variabel x och visas movinav2 4, xx - nytt datavärde 4 och det nya resultatet lagras på variabel x och visas 4 3 2.Deskription av funktionen movinavg variabel r - är resultatet Den genomsnittliga listan som kommer att bli returnerad variabel i - är indexvariabeln och den pekar på slutet av dellistan listan är den genomsnittliga variabeln z - en hjälparvariabel. Funktionen använder variabel i för att bestämma vilka värden av listan som ska beaktas i nästa genomsnitt beräkning Vid varje iteration pekar variabeln i till det sista värdet i listan som ska användas i medelberäkningen. Så vi behöver bara ta reda på vilka som ska vara det första värdet i listan. Vi måste vanligtvis överväga p-element, så att Första elementet kommer att vara det som indexeras av ip 1 Men vid de första iterationerna kommer denna beräkning vanligen att vara negativ, så följande ekvation undviker negativa index max ip 1,1 eller, ordnar ekvationen, max ip, 0 1 Men antalet Element på de första iterationerna kommer också att vara mindre, det korrekta värdet blir slutindex - börja index 1 eller ordna ekvationen, i - max ip, 0 1 1 och sedan, i-max ip, 0 Variabel z håller den vanliga Värde max ip, 0 så startindex blir z 1 och Numberofelements kommer att vara iz. mid list, z 1, iz kommer att returnera listan över värde som kommer att bli summa summan kommer summa summa iz ri kommer att genomsnittsa dem och lagra resultatet på lämpligt ställe i resultatlistan. Fp1 skapar en partiell applikation Fastställa i detta fall andra och tredje parametrar.
No comments:
Post a Comment