rlist/0000755000176200001440000000000014114411362011404 5ustar liggesusersrlist/NAMESPACE0000644000176200001440000000324214114257115012630 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method("$<-",List) S3method("==",List) S3method("[",List) S3method("[<-",List) S3method("[[",List) S3method("[[<-",List) S3method(list.parse,character) S3method(list.parse,data.frame) S3method(list.parse,default) S3method(list.parse,matrix) S3method(print,List) S3method(str,List) S3method(subset,List) S3method(subset,list) S3method(summary,List) export(List) export(list.all) export(list.any) export(list.append) export(list.apply) export(list.cases) export(list.cbind) export(list.class) export(list.clean) export(list.common) export(list.count) export(list.do) export(list.exclude) export(list.expand) export(list.extract) export(list.filter) export(list.find) export(list.findi) export(list.first) export(list.flatten) export(list.group) export(list.if) export(list.insert) export(list.is) export(list.iter) export(list.join) export(list.last) export(list.load) export(list.map) export(list.maps) export(list.mapv) export(list.match) export(list.merge) export(list.names) export(list.order) export(list.parse) export(list.prepend) export(list.rbind) export(list.remove) export(list.reverse) export(list.sample) export(list.save) export(list.search) export(list.select) export(list.serialize) export(list.skip) export(list.skipWhile) export(list.sort) export(list.stack) export(list.subset) export(list.table) export(list.take) export(list.takeWhile) export(list.ungroup) export(list.unserialize) export(list.unzip) export(list.update) export(list.which) export(list.zip) export(tryEval) export(tryGet) importFrom(data.table,rbindlist) importFrom(stats,na.omit) importFrom(utils,modifyList) importFrom(utils,str) importFrom(utils,txtProgressBar) rlist/LICENSE0000644000176200001440000000004513650064303012413 0ustar liggesusersYEAR: 2014 COPYRIGHT HOLDER: Kun Ren rlist/README.md0000644000176200001440000001320014114257476012675 0ustar liggesusers # rlist [![Linux Build Status](https://travis-ci.org/renkun-ken/rlist.png?branch=master)](https://travis-ci.org/renkun-ken/rlist) [![Windows Build status](https://ci.appveyor.com/api/projects/status/github/renkun-ken/rlist?svg=true)](https://ci.appveyor.com/project/renkun-ken/rlist) [![codecov.io](https://codecov.io/github/renkun-ken/rlist/coverage.svg?branch=master)](https://codecov.io/github/renkun-ken/rlist?branch=master) [![CRAN Version](https://www.r-pkg.org/badges/version/rlist)](https://cran.r-project.org/package=rlist) rlist is a set of tools for working with list objects. Its goal is to make it easier to work with lists by providing a wide range of functions that operate on non-tabular data stored in them. This package supports list mapping, filtering, grouping, sorting, updating, searching, file input/output, and many other functions. Most functions in the package are designed to be pipeline friendly so that data processing with lists can be chained. **[rlist Tutorial](https://renkun-ken.github.io/rlist-tutorial/) is a highly recommended complete guide to rlist.** This document is also translated into [日本語](https://github.com/renkun-ken/rlist/blob/master/README.ja.md) (by [@teramonagi](https://github.com/teramonagi)). ## Installation Install the latest version from GitHub: ```r devtools::install_github("renkun-ken/rlist") ``` Install from [CRAN](https://cran.r-project.org/package=rlist): ```r install.packages("rlist") ``` ## Motivation In R, there are numerous powerful tools to deal with structured data stored in tabular form such as data frame. However, a variety of data is non-tabular: different records may have different fields; for each field they may have different number of values. It is hard or no longer straightforward to store such data in data frame, but the `list` object in R is flexible enough to represent such records of diversity. rlist is a toolbox to deal with non-structured data stored in `list` objects, providing a collection of high-level functions which are pipeline friendly. ## Getting started Suppose we have a list of developers, each of whom has a name, age, a few interests, a list of programming languages they use and the number of years they have been using them. ```r library(rlist) devs <- list( p1=list(name="Ken",age=24, interest=c("reading","music","movies"), lang=list(r=2,csharp=4)), p2=list(name="James",age=25, interest=c("sports","music"), lang=list(r=3,java=2,cpp=5)), p3=list(name="Penny",age=24, interest=c("movies","reading"), lang=list(r=1,cpp=4,python=2))) ``` This type of data is non-relational since it does not well fit the shape of a data frame, yet it can be easily stored in JSON or YAML format. In R, list objects are flexible enough to represent a wide range of non-relational datasets like this. This package provides a wide range of functions to query and manipulate this type of data. The following examples use `str()` to show the structure of the output. ### Filtering Filter those who like music and has been using R for more than 3 years. ```r str( list.filter(devs, "music" %in% interest & lang$r >= 3) ) ``` ``` List of 1 $ p2:List of 4 ..$ name : chr "James" ..$ age : num 25 ..$ interest: chr [1:2] "sports" "music" ..$ lang :List of 3 .. ..$ r : num 3 .. ..$ java: num 2 .. ..$ cpp : num 5 ``` ### Selecting Select their names and ages. ```r str( list.select(devs, name, age) ) ``` ``` List of 3 $ p1:List of 2 ..$ name: chr "Ken" ..$ age : num 24 $ p2:List of 2 ..$ name: chr "James" ..$ age : num 25 $ p3:List of 2 ..$ name: chr "Penny" ..$ age : num 24 ``` ### Mapping Map each of them to the number of interests. ```r str( list.map(devs, length(interest)) ) ``` ``` List of 3 $ p1: int 3 $ p2: int 2 $ p3: int 2 ``` ### More functions In addition to these basic functions, rlist also supports various types of grouping, joining, searching, sorting, updating, etc. For the introduction to more functionality, please go through the [rlist Tutorial](https://renkun-ken.github.io/rlist-tutorial/). ## Lambda expression In this package, almost all functions that work with expressions accept the following forms of lambda expressions: - Implicit lambda expression: `expression` - Univariate lambda expressions: * `x ~ expression` * `f(x) ~ expression` - Multivariate lambda expressions: * `f(x,i) ~ expression` * `f(x,i,name) ~ expression` where `x` refers to the list member itself, `i` denotes the index, `name` denotes the name. If the symbols are not explicitly declared, `.`, `.i` and `.name` will by default be used to represent them, respectively. ```r nums <- list(a=c(1,2,3),b=c(2,3,4),c=c(3,4,5)) list.map(nums, c(min=min(.),max=max(.))) list.filter(nums, x ~ mean(x)>=3) list.map(nums, f(x,i) ~ sum(x,i)) ``` ## Using pipeline ### Working with pipe syntax Query the name of each developer who likes music and uses R, and put the results in a data frame. ```r devs |> list.filter("music" %in% interest & "r" %in% names(lang)) |> list.select(name,age) |> list.stack ``` ``` name age 1 Ken 24 2 James 25 ``` The example above uses the pipe syntax `|>` introduced in R 4.1 that chains commands in a fluent style. ### List environment `List()` function wraps a list within an environment where almost all list functions are defined. Here is the List-environment version of the previous example. ```r ldevs <- List(devs) ldevs$filter("music" %in% interest & "r" %in% names(lang))$ select(name,age)$ stack()$ data ``` ``` name age 1 Ken 24 2 James 25 ``` ## License This package is under [MIT License](https://opensource.org/licenses/MIT). rlist/data/0000755000176200001440000000000013650064303012320 5ustar liggesusersrlist/data/nyweather.rda0000644000176200001440000004462313650064303015027 0ustar liggesusersBZh91AY&SYQY9}a>#ɀXӫglֶim>g1VMlC 1UXx@x)=YWBP QH5ӛ\O\aJ5T`0 z f(4=ꄔ8ws@(4D444AѠ`F##S MF&@ F)OSM4&#FEL xj4OjLOI=A h ="MOTh@ =A@z P@4I"C&zh4Aш=FC@SMM 4hRDi4M1FdҞSOHm&DS6hI?SF5?SP~MGOL4&oI?Rii~=Fh#&L&MIɢx2h414FBif'ƩSOA7MSMzzI#@i 44 4P{5wu-]x~W|{=E:_Ch"nA"A J(#㨌TZUU,IyPTڕKoSH[𮚂Sl5ZP("޷{O<n^:/e.usxN|O{zn' toվ>ˊO ݯW<5s~]17g;..D 񊪪":"6ACfcbUUU5hҦEF0),P?."뼡kERD iJ' /]IglGrs^}[ \iq  (ABzj/^; _8M=3»v-}hxnDճ646+ TY454OeP|89OOR)] gScGH2>/.]/tSH5;CRӜf2Nou<΂}׆^:(O]GV~ϗB;,E3˲*N|n~4@=FZ ̠۞rg9m18k h1@!x h6vdx0{Q'ۍoM8"fس^NXAʂcPukl~r^t ӧ P 9C#!,_>Br<`f@ ~YuC, A o[ʏnH8IAWǕhT~ҹm*v;7CC4=333Rv֡;u*{D|+3]f4 FO[܎A\lfh:4ډ#Xѵ9s#lFW;L ƗF.$)+n|5⌳mWhZ/|3Wۨ]흝EgG+# V6hlϕe`a\ie\lEڳmw_E'}=kwe:!M' Һ%(<jԻ&{rO3i8hO ǎ06G1=)8ogm6[C+UxʭUR\Hp5K pYq+]]LI⸭/f,%[DaByHW}0hG1Ë4EyK6ǚP)xZ&(͘kv}3Y 5~fW }=02e|l# ցvãŕ[mχpacٚ<`vsސ-8wm<;X\CjK.3 ZZ*qokؽOl ~] A{jF5!buCQڑ"&)с` 1$SʪΖ#˧5TrY8JPkdoNWqL)Vd HP& Tja`D>-i(!~sq0 0%$ (fW[Q41VtTi2nT(Gr?p$BD4qqx;~'/'|("SL];ysn1j'rm)o`nOӏ֕j3# ;7yRa2:iPf%B h!AiHQC}P/2 U4G~p-< niFJp =)- \[+1cCrݟyi"y$4a$@s] e8"Nbʓ}wT9 ӥc#$$]k=2 _CbYZ=WTyIZo@#ƘP9!;RVY}+=/)ggt$<2uI*@`ePAs@}qq\OvƽIx4\N`*Q_?-f Ϩ Eg &ܦ< A!z/yH%~)tnǞ ~/*t Ty+ێ=fy^v)(} e޾zGӯH@ 8 7=TN9^\yA'^zx+}:$7i -o@@w{Oqx0>jA|;O!:$,b0d AecLвOI|P[q y-}x !h8.woݯ:n؏?zCS,bnws`Wio}Sq#0C*>xL-{W|To/Ɖx\Xz[-eʃlz%C "6ڞA ˣE.{[}^yx~u<~[txGQ\uS#4KJ Ȇyvqs1 G ; v{df@ԓ]]wpE|Oi9v;]л"Fҍ4Y̮$4CGs"c| 8N}C4B:sm;hVT c,mɾ5=-kS3v*K5ҍȄZQ.`"%2'wsolt+!?F gr!jrB" xeB5 wjdðWٟޕ+Ÿq0=e @CPcR>GÛ9 q'9dENu33:7c꒡cQrjA~bq Ĵ RoYp|oMzY%+? w{0vN@Lw( ga>(f`Ÿ#Cn^o7DHʆAFD>gE" >uW̞L!\I'YtrffbDfĘ{ ZT"z= L ?HZjI 8 =< &q]U^cne+*jfUU>GĢĪx̣N eXCafc68bR-FXAlkf&QrXYUnTh_"E'gK<ó"qTGbauҮ!t5#QЩ:"&R*kdP̈ED:Zk#(ޟؓ~ L#3c1vK $F`9>`]~P#Y fA[фh-%Q3al12tb]&ݱf;& Pۡ6 m ;DdY4bHv$=䮳F0*WI+)(bq \ֶ!ur(xϩz\42+l!qpkphn”?eCˆigr8*hP͂o ]+yT!휓%Ȟc~UGD.ǀq*H@}fy./AuvZQ.AB!: w8+LӲoZЈ׳>OPSHpNP:J:j!rZ,(>FL#a"h2.#! Rmtn׾89-/\NJ?K9VAL e}'(^5S:@r]J\3&&1CNԹp'FA2ƯZ\+aCWF9䪌JB)%K #M*(|Ͻaz7XJ9l|hҳe\Bl-+bQ9EHTmå[4QeY07iU9R:ދWVgӤ&%IV^~)w4ڇg'58QԢ(JItt]wZg)&1*0NXmޮiDXEVwMCY,hJTѺDH@Jz5Ƒ9ޒpt:TM,+  9:ktjMaIbZ/{RZN8}gX8dj֚|(NҬch_rZYV7|A ZDŽG=9][G ƉV`)UQ(u^/nt>Ϟ9.@7C8 fFd 0_"( \e]1W\σQӭ*bժj\gJ+[Z|v?=An,YQ*R$PHz(zDrYaW`P-jT.u0!c VԓLfDiU[ Q[RCPSBJ'H[)Rmh-#1H[VbڱkQEQ5Z-UZH ЅȬ!$2Ŵ6!JÈ!yx4į[J⮃$ʴ#8J l21XѶmLMc[TIQXXFѵElF(űmbحZ*ű K%(AZ,Ej-ch$!R&C53K ƻ` 0` 0`R)JR)JR)JR DrJ5BZQX$"i@ZdEHL"di]cdt(&m?؂l\ :%$?3lMJ>΄" fڪfUUY&B  Cf5L+\ʭt[U,PƴT+JTZe1-(.{!7]H?()_`Bjĺ̑VJR{{, F uϽyܛYFFaə b5taF4 B(Q. 4{nlQ&mlk{hh ui(EJJmV)UMi p*"﯍v2(ɚ3*2KUhFjT(A" EFDUbj6KjUIZ&DXԳS+&E֌AUV&Ul`)XDhTQH3AouR>B;f&oX2&0**2 &-geX\`Id*YȠ *z{/ko9Tn]M#fTlKKqK|wAQlk Fm%*KniZxhU4}OSpMF/'0ڡƐH#-F4:>!tթjjj|%/p]`-7o߽D3ɿP1I6fjŻnm1|8HZ_^L=}~zw&D%X)I #3]޿ox&ҋ[ʩhk}M]]m˥Oיt0{nR5I~Y8zN?PB *Bib@f#u7NEJ?ټ[S.w =_I) A$YVRDc CRn77.xњ-i8 VT͚=N8OQjbYHU1QKWܦcѬfr;B&s5!7DP" AtAڰOFA[窷ϳFV` M~ȃͭȭ[DɯUȯIO#'ΘC1#8U`fb0!!g84`DZP&y]g_spD#w 8q"llFGu9Ep'g&exsͬ'͢~P=GM\;='h{س0 M`o>@xu)WHUvj"#c0 v؍y@Ϡ*6,+NKm2xt;\tM{v75Q${Oc6_t[ahq46Q=&3ܑq3;Nc_L8xF0 qO@#$xIE) %%))6BJD4C@Pf JL5L4"c04`D)LBɩ J!2m~܂\0 CE8Eͭ]{ 磁1Ao67cFF5a^2 `:Ђ_>~.7\Dx{KnMlޣ58C-6=G9X9׍6[HuZQq^E;E^$rc<[_$_n.`F{~sD; .w0l~PuGCv>6g`@+4@@ tEܼE77UjyT^U<1yb;{4线Og /ΘM|`K#߭Ɓ6/a"]3񣠀#^y#o'E;sIZn4[u6cE3[8Oyw7XGT1DJA!`H^B/*%$|=Tϗ_g?&3'qsĿJ~7קՕf4~eΈ*mW@*|_D6JcĻwkqKcdMgW%oΟ?l( lho;%:gؽ\S<„HUAT@͵zNmU ɡ(2m޷Iok<8fqWA3U_#\Xr rrrfn_ཿxxDͅc0fM/K$ f ĂײW16'm "mi藣 %IĦa3jp4A9[/B6mr-(:x.mHghjpguz9"I@W*wүYZGW-9 TssÛgܨ=6zj@AUAHBisTViJ7P _ib}"2mHn9}9!R {p |W;lq 8 "ZC,BCZF= ES\HQHT\VThvyd IT  )"p&RŴ,@0oMDB!yKY0 x:A_:]/Ua}^qDB$= Is(7HnfG}@[{w<`TT?b"1kc;wdxn3xNE1vt x݋'!]}E_kk+{y;7my]FnK_b v O̫z+]TL(~W*<9ш[e#zTiFR:êヌww!F'+gKwdP,Cԕts*"(o rvz>.9~zVe lb#L*2J2]m6bhL%SbubQ:"!P.DFBcme+)D(%i N])X(GDhC.])1(L؊;jGT 1:Ne\9Ydn(BB*HRhqїWM]EeULXTі@DHDUɩ(qRGhUlC^3Te/pP.Dr3_S*:Ϥ"?YU$U*s~fQ"~(UZpR"RQje`ZU[KJVF®q/f*}?:jzиj\ Hݘ.:1CۚPPCsy'Xe+}XJQ0F sC ,̩ ':r̳ s245m&uؙMZdʶ(;&ei (֢j6R#RE#V.)!FRZճM^Jř1jj!^T;(ON1y&q;74mHF\nbePM|BP͙1NiM1nD . uvcvk-xXWcۼan%Cvը]6"6%ՒK',GZ] Be\VW0k[#݁ D 9+* [Bl#e6}ICQ)_*)ڑQFJ4'N36Zf@:M*8=:986U nS wXbH"(<=!jqAs*gŕg`I-de@+ RBЦJ1d4XFfp|J@}$#A1 saYZ%#8N8+RoWB}8ژsWE+8Np뺧iQH>N{QapSs)%g'za΅ ƳAϒّ}`G*8dgp`4X!+ A>$А8^Ή.A:g'5HNsEa*Rq,ϴn&բEglvK=kcdMz\]D!%A1cIVeD w9t!%\[pAs ۨUc CBR eD.X0hMq JN@v`\ANSHwXq .jRVwRI܈dH{*ఊ־蟐E_8nw^F_U }$y&ݏ{;U j]FUӽ G $zDq9|? (*8]--j(eTVyqmHW"v( gI$ǀI^ zPktCF߷.]qG"ɀ}G(~-'sEaW)O/)TQ=FWݰw;| e Đ ٧%] __I>񧗁nܛ;/'bJ/5ڎn;D+ zzbwݰ o uuz_nSv.33a5vӏb`fQw^~ρw~{z/5(!VP<P9^SNeHe {lri7 ̸eK+m?ͱ֗UL ;P8'axqC \;UHO^@5Z2*޼ =OwCr۞>#xZ8l,<7O\=,F/!n'|>zybi}59t]]꪿\5_6PY5* {;^ם}׵9.;} X[>y@ 4 VfҠId|5h %O]+I¢';riٷ|-!^(Zπt]B }K].*(Pj]UZև;r, ZcniuntWRuJeO>*2h FjOJK ^ /HŠzHVZynffeGy3+X+&bڹ0yֳN_.SY̡*goޗW@fcܠ\n뷹Xm--Xr`Ma-9 uvh/n^}rKm\waY7y,v?ɤ5dNg}t]۟Ѳ6ɠIo;zo}1^AJ&J//d%R JL88X+=?Uyde9(yc3\ga=M>Az΍{*WM`Mr4bP BRAr$>dmcHQ-b? _V˺VWd6 L2Z1 -#|70'<:|+ lT<Aƒ#7?]w|ha0zr]S.ŀ䵸:Bkb_۟줥]R!S}7a ɤNYh-fha~yLBr♛bf&l79-vj%+Y#|C_R:PH*{'a[-D 9 fW@l뽻:߿)1Pst_{?3̨l-%Q/}}降Y¥m$z7ˎQ-\GTrJc;$ 8SCH@ Dw5Z,ŦEgKv53'e۷yb|zu(_9I&]Qqd::D G+﬌X҃Lp{Z_jpzy3xXiw%3āK&Cp=>{nTx|V]ҏuvx>=gU=t퍇w15TR6>yo8{ ٞC^PPreAP Y(3XSR-_J|Vo[ 5t}75k̹m 1r/TMPKU MvKͮ֠*;fX7ϯR</%'{ w2>m5O7jxvG w>nypTS w}dwq0.p!i%rlist/man/0000755000176200001440000000000014114255253012164 5ustar liggesusersrlist/man/list.maps.Rd0000644000176200001440000000125213650064674014376 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.map.R \name{list.maps} \alias{list.maps} \title{Map multiple lists with an expression} \usage{ list.maps(expr, ...) } \arguments{ \item{expr}{An implicit lambda expression where only \code{.i} and \code{.name} are defined.} \item{...}{Named arguments of lists with equal length. The names of the lists are available as symbols that represent the element for each list.} } \description{ Map multiple lists with an expression } \examples{ \dontrun{ l1 <- list(p1=list(x=1,y=2), p2=list(x=3,y=4), p3=list(x=1,y=3)) l2 <- list(2,3,5) list.maps(a$x*b+a$y,a=l1,b=l2) list.maps(..1$x*..2+..1$y,l1,l2) } } rlist/man/callwith.Rd0000644000176200001440000000133213650321110014247 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/functions.R \name{callwith} \alias{callwith} \title{Evaluate a function with a modified default values} \usage{ callwith(fun, args, dots = list(), keep.null = FALSE, envir = parent.frame()) } \arguments{ \item{fun}{either a function or a non-empty character string naming the function to be called} \item{args}{a list of values to modify the default arguments of the function} \item{dots}{the user-specific input (usually from ...)} \item{keep.null}{\code{TRUE} to keep \code{NULL} values after argument modifications} \item{envir}{the environment to evaluate the function call} } \description{ Evaluate a function with a modified default values } rlist/man/list.remove.Rd0000644000176200001440000000122713650064674014735 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.remove.R \name{list.remove} \alias{list.remove} \title{Remove members from a list by index or name} \usage{ list.remove(.data, range = integer()) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{range}{A numeric vector of indices or a character vector of names to remove from \code{.data}} } \description{ Remove members from a list by index or name } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.remove(x, 'p1') list.remove(x, c(1,2)) } rlist/man/list.find.Rd0000644000176200001440000000154013650064674014356 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.find.R \name{list.find} \alias{list.find} \title{Find a specific number of elements in a list or vector satisfying a given condition} \usage{ list.find(.data, cond, n = 1L) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{cond}{A logical lambda expression} \item{n}{The number of items to find. (\code{n = 1L} by default)} } \value{ A list or vector of at most \code{n} elements in \code{.data} found to satisfy \code{cond}. } \description{ Find a specific number of elements in a list or vector satisfying a given condition } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.find(x, type=='B', 1) list.find(x, min(score$c1,score$c2) >= 9) } rlist/man/list.any.Rd0000644000176200001440000000171113650064674014225 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.all.R \name{list.any} \alias{list.any} \title{Examine if a condition is true for at least one list element} \usage{ list.any(.data, cond, na.rm = FALSE) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{cond}{A logical lambda expression} \item{na.rm}{logical. If true \code{NA} values are ignored in the evaluation.} } \value{ \code{TRUE} if \code{cond} is evaluated to be \code{TRUE} for any element in \code{.data}. } \description{ Examine if a condition is true for at least one list element } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.any(x,type=='B') list.any(x,mean(unlist(score))>=6) list.any(x, score$c2 > 8 || score$c3 > 5, na.rm = TRUE) list.any(x, score$c2 > 8 || score$c3 > 5, na.rm = FALSE) } \seealso{ \code{\link{list.all}} } rlist/man/tryGet.Rd0000644000176200001440000000155313650064674013746 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils.R \name{tryGet} \alias{tryGet} \title{Try to get the value of a symbol if exists or return a default value} \usage{ tryGet(symbol, def = NULL, ..., envir = parent.frame()) } \arguments{ \item{symbol}{the symbol to examine} \item{def}{the default value if the symbol does not exist} \item{...}{additional parameters passed to \code{exists} and \code{get}} \item{envir}{the environment to examine whether the symbol exists and get the symbol} } \description{ Try to get the value of a symbol if exists or return a default value } \details{ By default, the symbol is examined in \code{envir} without inheritance, that is, if the symbol does not exist in \code{envir} the default value \code{def} will be returned. } \examples{ x <- list(a=c(x=1,y=2),b=c(x=2,p=3)) list.map(x, tryGet(y,0)) } rlist/man/rlist-package.Rd0000644000176200001440000000137314114255757015216 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rlist.R \docType{package} \name{rlist-package} \alias{rlist-package} \title{The rlist package} \description{ rlist is a set of tools for working with list objects. Its goal is to make it easier to work with lists by providing a wide range of functions that operate on non-tabular data stored in them. The package provides a set of functions for data manipulation with list objects, including mapping, filtering, grouping, sorting, updating, searching, and other useful functions. Most functions are designed to be pipeline friendly so that data processing with lists can be chained. rlist Tutorial (\url{https://renkun-ken.github.io/rlist-tutorial/}) is a complete guide to rlist. } rlist/man/list.subset.Rd0000644000176200001440000000100113650064674014733 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.subset.R \name{list.subset} \alias{list.subset} \title{Subset a list} \usage{ list.subset() } \description{ Subset a list } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.subset(x, c('p1','p2')) list.subset(x, grepl('^p', names(x))) \dontrun{ list.subset(x, stringdist::stringdist(names(x), 'x1') <= 1) } } rlist/man/list.sort.Rd0000644000176200001440000000147413650064674014433 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.order.R \name{list.sort} \alias{list.sort} \title{Sort a list by given expressions} \usage{ list.sort(.data, ..., na.last = NA) } \arguments{ \item{.data}{a \code{list} or \code{vector}} \item{...}{A group of lambda expressions. For each expression, the data is sorted ascending by default unless the expression is enclosed by ().} \item{na.last}{The way to deal with \code{NA}s.} } \description{ Sort a list by given expressions } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.sort(x, type, (score$c2)) # sort by score$c2 in descending order list.sort(x, min(score$c1,score$c2)) } \seealso{ \code{\link{list.order}} } rlist/man/list.append.Rd0000644000176200001440000000102613650064674014704 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.insert.R \name{list.append} \alias{list.append} \title{Append elements to a list} \usage{ list.append(.data, ...) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{...}{A \code{vector} or \code{list} to append after \code{x}} } \description{ Append elements to a list } \examples{ \dontrun{ x <- list(a=1,b=2,c=3) list.append(x,d=4,e=5) list.append(x,d=4,f=c(2,3)) } } \seealso{ \code{\link{list.prepend}}, \code{\link{list.insert}} } rlist/man/list.sample.Rd0000644000176200001440000000143613650064674014723 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.sample.R \name{list.sample} \alias{list.sample} \title{Sample a list or vector} \usage{ list.sample(.data, size, replace = FALSE, weight = 1, prob = NULL) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{size}{\code{integer}. The size of the sample} \item{replace}{\code{logical}. Should sampling be with replacement?} \item{weight}{A lambda expression to determine the weight of each list member, which only takes effect if \code{prob} is \code{NULL}.} \item{prob}{A \code{vector} of probability weights for obtaining the elements of the list being sampled.} } \description{ Sample a list or vector } \examples{ x <- list(a = 1, b = c(1,2,3), c = c(2,3,4)) list.sample(x, 2, weight = sum(.)) } rlist/man/set_argnames.Rd0000644000176200001440000000141013650321110015105 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/functions.R \name{set_argnames} \alias{set_argnames} \title{Make names for unnamed symbol arguments} \usage{ set_argnames(args, data = args) } \arguments{ \item{args}{the unevaluated argument list} \item{data}{the list to be named (\code{args} by default)} } \description{ Make names for unnamed symbol arguments } \details{ The elements of an unevaluated list of arguments may or may not have names as given by user. For example, \code{list.select} requires user to specify the fields to select. These fields are unevaluated arguments, some of which are symbols and others are calls. For the symbols, it is natural to make the resulted lists to have the same name for the particular arguments. } rlist/man/list.table.Rd0000644000176200001440000000155013650064674014526 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.table.R \name{list.table} \alias{list.table} \title{Generate a table for a list by expression} \usage{ list.table(.data, ..., table.args = list(useNA = "ifany")) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{...}{A group of lambda expressions. If missing, \code{table} will be directly called upon \code{.data} with \code{table.args}.} \item{table.args}{\code{list}. The additional parameters passed to \code{table}} } \description{ Generate a table for a list by expression } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.table(x, type) list.table(x, type, c1 = score$c1) list.table(x, type, score$c1, table.args = list(dnn=c('type','c1'))) } rlist/man/list.unserialize.Rd0000644000176200001440000000123313650064674015767 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.serialize.R \name{list.unserialize} \alias{list.unserialize} \title{Unserialize a file} \usage{ list.unserialize(file, type = tolower(tools::file_ext(file)), ...) } \arguments{ \item{file}{The file as input} \item{type}{The type of serialization, including native unserializer and json unserializer, which is by default determined by file extension} \item{...}{Additional parameters passed to the unserializer function} } \description{ Unserialize a file } \examples{ \dontrun{ list.unserialize('test.dat') list.unserialize('test.json') } } \seealso{ \code{\link{list.serialize}} } rlist/man/list.names.Rd0000644000176200001440000000127713650064674014550 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.names.R \name{list.names} \alias{list.names} \title{Get or set the names of a list by expression} \usage{ list.names(.data, expr) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{expr}{the expression whose value will be set as the name for each list element. If missing then the names of the list will be returned. If \code{NULL} then the names of the list will be removed.} } \description{ Get or set the names of a list by expression } \examples{ list.names(c(1,2,3)) list.names(c(a=1,b=2,c=3)) list.names(c(1,2,3),letters[.]) list.names(list(list(name='A',value=10),list(name='B',value=20)), name) } rlist/man/list.take.Rd0000644000176200001440000000114513650064674014363 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.take.R \name{list.take} \alias{list.take} \title{Take a number of elements} \usage{ list.take(.data, n, force = FALSE) } \arguments{ \item{.data}{\code{list} or \code{vector}} \item{n}{\code{integer}. The number of elements to take} \item{force}{\code{TRUE} to disable the length check} } \description{ Take the first \code{n} elements out from a list or vector. } \examples{ x <- list(a=1,b=2,c=3) list.take(x,1) list.take(x,10) } \seealso{ \code{\link{list.takeWhile}}, \code{\link{list.skip}}, \code{\link{list.skipWhile}} } rlist/man/list.all.Rd0000644000176200001440000000170613650064674014212 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.all.R \name{list.all} \alias{list.all} \title{Examine if a condition is true for all elements of a list} \usage{ list.all(.data, cond, na.rm = FALSE) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{cond}{A logical lambda expression} \item{na.rm}{logical. If true \code{NA} values are ignored in the evaluation.} } \value{ \code{TRUE} if \code{cond} is evaluated to be \code{TRUE} for all elements in \code{.data}. } \description{ Examine if a condition is true for all elements of a list } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.all(x, type=='B') list.all(x, mean(unlist(score))>=6) list.all(x, score$c2 > 8 || score$c3 > 5, na.rm = TRUE) list.all(x, score$c2 > 8 || score$c3 > 5, na.rm = FALSE) } \seealso{ \code{\link{list.any}} } rlist/man/list.serialize.Rd0000644000176200001440000000126713650064674015433 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.serialize.R \name{list.serialize} \alias{list.serialize} \title{Serialize a list} \usage{ list.serialize(x, file, type = tools::file_ext(file), ...) } \arguments{ \item{x}{\code{list}} \item{file}{The file for output} \item{type}{The type of serialization, including native serializer and json serializer, which is by default determined by file extension} \item{...}{Additional parameters passed to the serializer function} } \description{ Serialize a list } \examples{ \dontrun{ x <- list(a=1,b=2,c=3) list.serialize(x,'test.dat') list.serialize(x,'test.json') } } \seealso{ \code{\link{list.unserialize}} } rlist/man/list.parse.Rd0000644000176200001440000000262613650064674014556 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.parse.R \name{list.parse} \alias{list.parse} \alias{list.parse.default} \alias{list.parse.matrix} \alias{list.parse.data.frame} \alias{list.parse.character} \title{Convert an object to list with identical structure} \usage{ list.parse(x, ...) \method{list.parse}{default}(x, ...) \method{list.parse}{matrix}(x, ...) \method{list.parse}{data.frame}(x, ...) \method{list.parse}{character}(x, type, ...) } \arguments{ \item{x}{\code{An object}} \item{...}{Additional parameters passed to converter function} \item{type}{The type of data to parse. Currently json and yaml are supported.} } \value{ \code{list} object representing the data in \code{x} } \description{ This function converts an object representing data to list that represents the same data. For example, a \code{data.frame} stored tabular data column-wisely, that is, each column represents a vector of a certain type. \code{list.parse} converts a \code{data.frame} to a list which represents the data row-wisely so that it can be more convinient to perform other non-tabular data manipulation methods. } \examples{ x <- data.frame(a=1:3,type=c('A','C','B')) list.parse(x) x <- matrix(rnorm(1000),ncol=5) rownames(x) <- paste0('item',1:nrow(x)) colnames(x) <- c('a','b','c','d','e') list.parse(x) z <- ' a: type: x class: A registered: yes ' list.parse(z, type='yaml') } rlist/man/list.first.Rd0000644000176200001440000000126713650064674014573 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.first.R \name{list.first} \alias{list.first} \title{Find the first element that meets a condition} \usage{ list.first(.data, cond) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{cond}{a logical lambda expression} } \description{ Find the first element that meets a condition } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.first(x, score$c1 < 10) list.first(x, score$c1 < 9 || score$c3 >= 5) # NULL for all results are NA or FALSE } \seealso{ \code{\link{list.last}} } rlist/man/list.stack.Rd0000644000176200001440000000156413650064674014551 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.stack.R \name{list.stack} \alias{list.stack} \title{Stack all list elements to tabular data} \usage{ list.stack(.data, ..., data.table = FALSE) } \arguments{ \item{.data}{\code{list} of \code{vector}s, \code{list}s, \code{data.frame}s or \code{data.table}s.} \item{...}{additional parameters passed to \code{data.table::rbindlist}.} \item{data.table}{\code{TRUE} to keep the result as \code{data.table}} } \description{ Stack all list elements to tabular data } \examples{ \dontrun{ x <- lapply(1:3, function(i) { list(a=i,b=i^2) }) list.stack(x) x <- lapply(1:3, function(i) { list(a=i,b=i^2,c=letters[i])}) list.stack(x) x <- lapply(1:3, function(i) { data.frame(a=i,b=i^2,c=letters[i]) }) list.stack(x) x <- lapply(1:3, function(i) { data.frame(a=c(i,i+1), b=c(i^2,i^2+1))}) list.stack(x) } } rlist/man/list.filter.Rd0000644000176200001440000000206113650064674014722 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.filter.R \name{list.filter} \alias{list.filter} \title{Filter a list or vector by a series of conditions} \usage{ list.filter(.data, ...) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{...}{logical conditions} } \value{ elements in \code{.data} satisfying all conditions } \description{ The function recursively filters the data by a given series of conditions. The filter can be a single condition or multiple conditions. \code{.data} will be filtered by the first condition; then the results will be filtered by the second condition, if any; then the results will be filtered by the third, if any, etc. The results only contain elements satisfying all conditions specified in \code{...}. } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.filter(x, type=='B') list.filter(x, min(score$c1, score$c2) >= 8) list.filter(x, type=='B', score$c2 >= 8) } rlist/man/list.zip.Rd0000644000176200001440000000121013650064674014232 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.zip.R \name{list.zip} \alias{list.zip} \title{Combine multiple lists element-wisely.} \usage{ list.zip(..., use.argnames = TRUE, use.names = TRUE) } \arguments{ \item{...}{\code{list}s} \item{use.argnames}{\code{logical}. Should the names of the arguments be used as the names of list items?} \item{use.names}{\code{logical}. Should the names of the first argument be used as the zipped list?} } \description{ Combine multiple lists element-wisely. } \examples{ x <- list(1,2,3) y <- list('x','y','z') list.zip(num=x,sym=y) } \seealso{ \code{\link{list.unzip}} } rlist/man/list.cbind.Rd0000644000176200001440000000126213650064674014516 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.do.R \name{list.cbind} \alias{list.cbind} \title{Bind all list elements by column} \usage{ list.cbind(.data) } \arguments{ \item{.data}{\code{list}} } \description{ The function binds all list elements by column. Each element of the list is expected to be an atomic vector, \code{data.frame}, or \code{data.table} of the same length. If list elements are also lists, the binding will flatten the lists and may produce undesired results. } \examples{ x <- list(data.frame(i=1:5,x=rnorm(5)), data.frame(y=rnorm(5),z=rnorm(5))) list.cbind(x) } \seealso{ \code{\link{list.cbind}}, \code{\link{list.stack}} } rlist/man/nyweather.Rd0000644000176200001440000000103114114255730014454 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/data.R \docType{data} \name{nyweather} \alias{nyweather} \title{New York hourly weather data} \format{ See \url{https://openweathermap.org/weather-data} } \usage{ nyweather } \description{ A non-tabular data of the hourly weather conditions of the New York City from 2013-01-01 to 2013-03-01. } \details{ Fetch date: 2014-11-23. Processed by rlist. To retrieve the data, please visit \url{https://openweathermap.org/api} for API usage. } \keyword{datasets} rlist/man/list.expand.Rd0000644000176200001440000000126313650064674014717 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.expand.R \name{list.expand} \alias{list.expand} \title{Create a list from all combinations of factors} \usage{ list.expand(...) } \arguments{ \item{...}{vectors or lists} } \value{ A list of all combinations of the supplied vectors or lists. } \description{ Create a list from all combinations of the supplied vectors or lists, extending the functionality of \link{expand.grid} from data frame to list. } \examples{ list.expand(x=1:10, y=c("a","b","c")) list.expand(x=list(c(1,2), c(2,3)), y = c("a","b","c")) list.expand( a=list(list(x=1,y="a"), list(x=2, y="b")), b=list(c("x","y"), c("y","z","w"))) } rlist/man/is.empty.Rd0000644000176200001440000000061113650321110014207 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/functions.R \name{is.empty} \alias{is.empty} \title{Check if an object is empty (has length 0)} \usage{ is.empty(x) } \arguments{ \item{x}{the object} } \description{ Check if an object is empty (has length 0) } \details{ A \code{NULL} value, zero-length vector or list have length zero, which is called empty. } rlist/man/list.insert.Rd0000644000176200001440000000134213650064674014742 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.insert.R \name{list.insert} \alias{list.insert} \title{Insert a series of lists at the given index} \usage{ list.insert(.data, index, ...) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{index}{The index at which the lists are inserted} \item{...}{A group of lists} } \description{ Insert a series of lists at the given index } \examples{ \dontrun{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.insert(x, 2, p2.1 = list(type='B',score=list(c1=8,c2=9))) } } \seealso{ \code{\link{list.append}}, \code{\link{list.prepend}} } rlist/man/list.takeWhile.Rd0000644000176200001440000000155713650064674015363 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.take.R \name{list.takeWhile} \alias{list.takeWhile} \title{Keep taking elements while a condition holds} \usage{ list.takeWhile(.data, cond) } \arguments{ \item{.data}{\code{list} or \code{vector}} \item{cond}{A logical lambda expression} } \description{ Keep taking elements out from a list or vector while a condition holds for the element. If the condition is violated for an element, the element will not be taken and all taken elements will be returned. } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.takeWhile(x, type=='B') list.takeWhile(x, min(score$c1,score$c2) >= 8) } \seealso{ \code{\link{list.take}}, \code{\link{list.skip}}, \code{\link{list.skipWhile}} } rlist/man/list.extract.Rd0000644000176200001440000000052713650064674015114 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.extract.R \name{list.extract} \alias{list.extract} \title{Extract an element from a list or vector} \usage{ list.extract() } \description{ Extract an element from a list or vector } \examples{ x <- list(a=1, b=2, c=3) list.extract(x, 1) list.extract(x, 'a') } rlist/man/subset.list.Rd0000644000176200001440000000157013650064674014746 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/subset.list.R \name{subset.list} \alias{subset.list} \title{Subset a list by a logical condition} \usage{ \method{subset}{list}(x, subset, select, ...) } \arguments{ \item{x}{The list to subset} \item{subset}{A logical lambda expression of subsetting condition} \item{select}{A lambda expression to evaluate for each selected item} \item{...}{Additional parameters} } \description{ Subset a list by a logical condition } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) subset(x, type == 'B') subset(x, select = score) subset(x, min(score$c1, score$c2) >= 8, data.frame(score)) subset(x, type == 'B', score$c1) do.call(rbind, subset(x, min(score$c1, score$c2) >= 8, data.frame(score))) } rlist/man/list.update.Rd0000644000176200001440000000220413650064674014716 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.update.R \name{list.update} \alias{list.update} \title{Update a list by appending or modifying its elements.} \usage{ list.update(.data, ..., keep.null = FALSE) } \arguments{ \item{.data}{\code{list}} \item{...}{A group of labmda expressions} \item{keep.null}{Should \code{NULL} values be preserved for \code{modifyList}} } \description{ The function updates each element of a list by evaluating a group of expressions in the scope of the element. If the name of an expression alreadys exists in an list element, then the field with the name will be updated. Otherwise, the value with the name will be appended to the list element. The functionality is essentially done by \code{modifyList}. } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.update(x, high=max(score$c1,score$c2), low=min(score$c1,score$c2)) list.update(x, exams=length(score)) list.update(x, grade=ifelse(type=='A', score$c1, score$c2)) list.update(x, score=list(min=0, max=10)) } rlist/man/list.mapv.Rd0000644000176200001440000000160113650064674014377 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.map.R \name{list.mapv} \alias{list.mapv} \title{Map each member of a list by an expression to a vector.} \usage{ list.mapv(.data, expr, as, use.names = TRUE) } \arguments{ \item{.data}{a \code{list} or \code{vector}} \item{expr}{a lambda expression} \item{as}{the mode to corece. Missing to \code{unlist} the mapped results.} \item{use.names}{Should the names of the results be preserved?} } \value{ A \code{vector} in which each element is mapped by \code{expr} in \code{.data} } \description{ Map each member of a list by an expression to a vector. } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.mapv(x, type) list.mapv(x, min(score$c1,score$c2)) } \seealso{ \code{\link{list.map}} } rlist/man/list.skipWhile.Rd0000644000176200001440000000154313650064674015400 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.skip.R \name{list.skipWhile} \alias{list.skipWhile} \title{Keep skipping elements while a condition holds} \usage{ list.skipWhile(.data, cond) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{cond}{A logical lambda expression} } \description{ Keep skipping elements in a list or vector while a condition holds for the element. As long as the condition is violated, the element will be kept and all remaining elements are returned. } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.skipWhile(x, type=='A') list.skipWhile(x, min(score$c1,score$c2) >= 8) } \seealso{ \code{\link{list.skip}}, \code{\link{list.take}}, \code{\link{list.takeWhile}} } rlist/man/list.count.Rd0000644000176200001440000000157013650064674014571 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.count.R \name{list.count} \alias{list.count} \title{Count the number of elements that satisfy given condition} \usage{ list.count(.data, cond) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{cond}{A logical lambda expression for each element of \code{.data} to evaluate. If \code{cond} is missing then the total number of elements in \code{.data} will be returned.} } \value{ An integer that indicates the number of elements with which \code{cond} is evaluated to be \code{TRUE}. } \description{ Count the number of elements that satisfy given condition } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.count(x, type=='B') list.count(x, min(unlist(score)) >= 9) } rlist/man/list.cases.Rd0000644000176200001440000000166113650064674014540 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.group.R \name{list.cases} \alias{list.cases} \title{Get all unique cases of a list field by expression} \usage{ list.cases(.data, expr, simplify = TRUE, sorted = TRUE) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{expr}{A lambda expression. The function will returns all cases of the elements if \code{expr} is missing.} \item{simplify}{\code{logical}. Should atomic vectors be simplified by \code{unlist}?} \item{sorted}{\code{logical}. Should the cases be sorted in ascending order?} } \description{ Get all unique cases of a list field by expression } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.cases(x,type) list.cases(x,mean(unlist(score))) foo <- list(x = LETTERS[1:3], y = LETTERS[3:5]) list.cases(foo) } rlist/man/dots.Rd0000644000176200001440000000036013650321110013411 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/functions.R \name{dots} \alias{dots} \title{Substitute ...} \usage{ dots(...) } \arguments{ \item{...}{parameters to substitute} } \description{ Substitute ... } rlist/man/list.class.Rd0000644000176200001440000000226413650064674014547 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.group.R \name{list.class} \alias{list.class} \title{Classify list elments into unique but non-exclusive cases} \usage{ list.class(.data, ..., sorted = TRUE) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{...}{keys} \item{sorted}{\code{TRUE} to sort the group keys. Ignored when the key has multiple entries.} } \value{ a list of possible cases each of which contains elements belonging to the case non-exclusively. } \description{ In non-tabular data, a certain field may take multiple values in a collection non-exclusively. To classify these elements into different cases, this function detects all possible cases and for each case all elements are examined whether to belong to that case. } \examples{ x <- list( p1=list(name='Ken',age=24, interest=c('reading','music','movies'), lang=list(r=2,csharp=4,python=3)), p2=list(name='James',age=25, interest=c('sports','music'), lang=list(r=3,java=2,cpp=5)), p3=list(name='Penny',age=24, interest=c('movies','reading'), lang=list(r=1,cpp=4,python=2))) list.class(x,interest) list.class(x,names(lang)) } rlist/man/list.ungroup.Rd0000644000176200001440000000277413650064674015147 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.group.R \name{list.ungroup} \alias{list.ungroup} \title{Ungroup a list by taking out second-level elements} \usage{ list.ungroup(.data, level = 1L, ..., group.names = FALSE, sort.names = FALSE) } \arguments{ \item{.data}{\code{list}} \item{level}{{integer} to indicate to which level of list elements should be ungroupped to the first level.} \item{...}{Preserved use of parameter passing} \item{group.names}{\code{logical}. Should the group names be preserved?} \item{sort.names}{\code{logical}. Should the members be sorted after ungrouping?} } \description{ This functon reverses the grouping operation by taking out second-level elements of a nested list and removing the labels of the first-level elements. For example, a list may be created from paged data, that is, its first-level elements only indicate the page container. To unpage the list, the first-level elements must be removed and their inner elements should be taken out to to the first level. } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) xg <- list.group(x, type) list.ungroup(xg) x <- list(a = list(a1 = list(x=list(x1=2,x2=3),y=list(y1=1,y2=3))), b = list(b1 = list(x=list(x1=2,x2=6),y=list(y1=3,y2=2)))) list.ungroup(x, level = 1) list.ungroup(x, level = 2) list.ungroup(x, level = 2, group.names = TRUE) } \seealso{ \code{\link{list.group}} } rlist/man/list.is.Rd0000644000176200001440000000146113650064674014053 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.is.R \name{list.is} \alias{list.is} \alias{list.if} \title{Return a logical vector that indicates if each member of a list satisfies a given condition} \usage{ list.is(.data, cond, use.names = TRUE) list.if(.data, cond, use.names = TRUE) } \arguments{ \item{.data}{\code{list}} \item{cond}{A logical lambda expression} \item{use.names}{\code{logical} Should the names of \code{.data} be kept?} } \description{ Return a logical vector that indicates if each member of a list satisfies a given condition } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.is(x,type=='B') list.is(x,min(score$c1,score$c2) >= 8) } rlist/man/list.join.Rd0000644000176200001440000000175413650064674014404 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.join.R \name{list.join} \alias{list.join} \title{Join two lists by single or multiple keys} \usage{ list.join(x, y, xkey, ykey, ..., keep.order = TRUE) } \arguments{ \item{x}{The first list} \item{y}{The second list} \item{xkey}{A lambda expression that determines the key for list \code{x}} \item{ykey}{A lambda expression that determines the key for list \code{y}, same to \code{xkey} if missing} \item{...}{The additional parameters passed to \code{merge.data.frame}} \item{keep.order}{Should the order of \code{x} be kept?} } \description{ Join two lists by single or multiple keys } \examples{ l1 <- list(p1=list(name='Ken',age=20), p2=list(name='James',age=21), p3=list(name='Jenny',age=20)) l2 <- list(p1=list(name='Jenny',age=20,type='A'), p2=list(name='Ken',age=20,type='B'), p3=list(name='James',age=22,type='A')) list.join(l1, l2, name) list.join(l1, l2, .[c('name','age')]) } rlist/man/list.rbind.Rd0000644000176200001440000000135213650064674014535 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.do.R \name{list.rbind} \alias{list.rbind} \title{Bind all list elements by row} \usage{ list.rbind(.data) } \arguments{ \item{.data}{\code{list}} } \description{ The function binds all list elements by row. Each element of the list is expected to be an atomic vector, \code{data.frame}, or \code{data.table}. If list elements are also lists, the result can be a list-valued matrix. In this case, \code{list.stack} may produce a better result. } \examples{ x <- lapply(1:3,function(i) { c(a=i,b=i^2)}) df <- lapply(1:3,function(i) { data.frame(a=i,b=i^2,c=letters[i])}) list.rbind(x) list.rbind(df) } \seealso{ \code{\link{list.cbind}}, \code{\link{list.stack}} } rlist/man/list.group.Rd0000644000176200001440000000161113650064674014571 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.group.R \name{list.group} \alias{list.group} \title{Divide list/vector elements into exclusive groups} \usage{ list.group(.data, ..., sorted = TRUE) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{...}{One or more expressions in the scope of each element to evaluate as keys} \item{sorted}{\code{TRUE} to sort the group keys. Ignored when the key has multiple entries.} } \value{ A list of group elements each contain all the elements in \code{.data} belonging to the group } \description{ Divide list/vector elements into exclusive groups } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.group(x, type) list.group(x, mean(unlist(score))) } \seealso{ \code{\link{list.ungroup}} } rlist/man/list.flatten.Rd0000644000176200001440000000177214114255657015101 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.flatten.R \name{list.flatten} \alias{list.flatten} \title{Flatten a nested list to a one-level list} \usage{ list.flatten(x, use.names = TRUE, classes = "ANY") } \arguments{ \item{x}{\code{list}} \item{use.names}{\code{logical}. Should the names of \code{x} be kept?} \item{classes}{A character vector of class names, or "ANY" to match any class.} } \description{ Flatten a nested list to a one-level list } \details{ The function is essentially a slightly modified version of \code{flatten2} provided by Tommy at \href{https://stackoverflow.com/a/8139959/2906900}{stackoverflow.com} who has full credit of the implementation of this function. } \examples{ p <- list(a=1,b=list(b1=2,b2=3),c=list(c1=list(c11='a',c12='x'),c2=3)) list.flatten(p) p <- list(a=1,b=list(x="a",y="b",z=10)) list.flatten(p, classes = "numeric") list.flatten(p, classes = "character") } \author{ \href{https://stackoverflow.com/users/662787/tommy}{Tommy} } rlist/man/list.exclude.Rd0000644000176200001440000000122013650064674015062 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.remove.R \name{list.exclude} \alias{list.exclude} \title{Exclude members of a list that meet given condition.} \usage{ list.exclude(.data, cond) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{cond}{A logical lambda expression to exclude items} } \description{ Exclude members of a list that meet given condition. } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.exclude(x, type=='B') list.exclude(x, min(score$c1,score$c2) >= 8) } rlist/man/list.order.Rd0000644000176200001440000000170313650064674014552 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.order.R \name{list.order} \alias{list.order} \title{Give the order of each list element by expression} \usage{ list.order(.data, ..., keep.names = FALSE, na.last = TRUE) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{...}{A group of lambda expressions} \item{keep.names}{Whether to keep the names of \code{x} in the result} \item{na.last}{The way to deal with \code{NA}s.} } \value{ an \code{integer} vector. } \description{ Give the order of each list element by expression } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.order(x, type, (score$c2)) # order by type (ascending) and score$c2 (descending) list.order(x, min(score$c1,score$c2)) list.order(x, min(score$c1,score$c2), keep.names=TRUE) } \seealso{ \code{\link{list.sort}} } rlist/man/list.reverse.Rd0000644000176200001440000000051113650064674015106 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.reverse.R \name{list.reverse} \alias{list.reverse} \title{Reverse a list} \usage{ list.reverse(.data) } \arguments{ \item{.data}{A \code{list} or \code{vector}} } \description{ Reverse a list } \examples{ x <- list(a=1,b=2,c=3) list.reverse(x) } rlist/man/list.merge.Rd0000644000176200001440000000227213650064674014540 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.merge.R \name{list.merge} \alias{list.merge} \title{Merge a number of named lists in sequential order} \usage{ list.merge(...) } \arguments{ \item{...}{named lists} } \description{ The function merges a number of lists in sequential order by \code{modifyList}, that is, the later list always modifies the former list and form a merged list, and the resulted list is again being merged with the next list. The process is repeated until all lists in \code{...} or \code{list} are exausted. } \details{ List merging is usually useful in the merging of program settings or configuraion with multiple versions across time, or multiple administrative levels. For example, a program settings may have an initial version in which most keys are defined and specified. In later versions, partial modifications are recorded. In this case, list merging can be useful to merge all versions of settings in release order of these versions. The result is an fully updated settings with all later modifications applied. } \examples{ l1 <- list(a=1,b=list(x=1,y=1)) l2 <- list(a=2,b=list(z=2)) l3 <- list(a=2,b=list(x=3)) list.merge(l1,l2,l3) } rlist/man/List.Rd0000644000176200001440000000226213650064674013401 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/List.R \name{List} \alias{List} \title{Create a \code{List environment} that wraps given \code{data} and most list functions are defined for chainable operations.} \usage{ List(data = list()) } \arguments{ \item{data}{A \code{list} or \code{vector}} } \description{ Create a \code{List environment} that wraps given \code{data} and most list functions are defined for chainable operations. } \details{ Most list functions are defined in \code{List environment}. In addition to these functions, \code{call(fun,...)} calls external function \code{fun} with additional parameters specifies in \code{...}. To extract the data from List \code{x}, call \code{x$data} or simply \code{x[]}. } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) m <- List(x) m$filter(type=='B')$ map(score$c1) [] m$group(type)$ map(g ~ List(g)$ map(score)$ call(unlist)$ call(mean) []) [] # Subsetting, extracting, and assigning p <- List(list(a=1,b=2)) p['a'] p[['a']] p$a <- 2 p['b'] <- NULL p[['a']] <- 3 } rlist/man/list.findi.Rd0000644000176200001440000000157113650064674014533 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.find.R \name{list.findi} \alias{list.findi} \title{Find the indices of a number of elements in a list or vector satisfying a given condition} \usage{ list.findi(.data, cond, n = 1L) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{cond}{A logical lambda expression} \item{n}{The number of items to find. (\code{n = 1L} by default)} } \value{ an integer vector consisting of the elements indices } \description{ Find the indices of a number of elements in a list or vector satisfying a given condition } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.findi(x, type=='B') list.findi(x, min(score$c1,score$c2) >= 8) list.findi(x, min(score$c1,score$c2) <= 8, n = 2) } rlist/man/list.save.Rd0000644000176200001440000000134613650064674014400 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.save.R \name{list.save} \alias{list.save} \title{Save a list to a file} \usage{ list.save(x, file, type = tools::file_ext(file), ...) } \arguments{ \item{x}{The list to save} \item{file}{The file for output} \item{type}{The type of output which, by default, is determined by file extension. Currently supports RData, RDS, JSON, YAML.} \item{...}{Additional parameters passed to the output function} } \value{ \code{x} will be returned. } \description{ Save a list to a file } \examples{ \dontrun{ x <- lapply(1:5,function(i) data.frame(a=i,b=i^2)) list.save(x, 'list.rds') list.save(x, 'list.rdata') list.save(x, 'list.yaml') list.save(x, 'list.json') } } rlist/man/list.last.Rd0000644000176200001440000000126113650064674014401 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.first.R \name{list.last} \alias{list.last} \title{Find the last element that meets a condition} \usage{ list.last(.data, cond) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{cond}{a logical lambda expression} } \description{ Find the last element that meets a condition } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.last(x, score$c1 < 10) list.last(x, score$c1 < 9 || score$c3 >= 5) # NULL for all results are NA or FALSE } \seealso{ \code{\link{list.first}} } rlist/man/list.map.Rd0000644000176200001440000000132513650064674014214 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.map.R \name{list.map} \alias{list.map} \title{Map each element in a list or vector by an expression.} \usage{ list.map(.data, expr) } \arguments{ \item{.data}{a \code{list} or \code{vector}} \item{expr}{A lambda expression} } \value{ A \code{list} in which each element is mapped by \code{expr} in \code{.data} } \description{ Map each element in a list or vector by an expression. } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.map(x, type) list.map(x, min(score$c1,score$c2)) } \seealso{ \code{\link{list.mapv}} } rlist/man/list.clean.Rd0000644000176200001440000000313613650064674014523 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.clean.R \name{list.clean} \alias{list.clean} \title{Clean a list by a function} \usage{ list.clean(.data, fun = is.null, recursive = FALSE) } \arguments{ \item{.data}{A \code{list} or \code{vector} to operate over.} \item{fun}{A \code{character} or a \code{function} that returns \code{TRUE} or \code{FALSE} to indicate if an element of \code{.data} should be removed.} \item{recursive}{\code{logical}. Should the list be cleaned recursively? Set to FALSE by default.} } \description{ This function removes all elements evaluated to be \code{TRUE} by an indicator function. The removal can be recursive so that the resulted list surely does not include such elements in any level. } \details{ Raw data is usually not completely ready for analysis, and needs to be cleaned up to certain standards. For example, some data operations require that the input does not include \code{NULL} values in any level, therefore \code{fun = "is.null"} and \code{recursive = TRUE} can be useful to clean out all \code{NULL} values in a list at any level. Sometimes, not only \code{NULL} values are undesired, empty vectors or lists are also unwanted. In this case, \code{fun = function(x) length(x) == 0L} can be useful to remove all empty elements of zero length. This works because \code{length(NULL) == 0L}, \code{length(list()) == 0L} and \code{length(numeric()) == 0L} are all \code{TRUE}. } \examples{ x <- list(a=NULL,b=list(x=NULL,y=character()),d=1,e=2) list.clean(x) list.clean(x, recursive = TRUE) list.clean(x, function(x) length(x) == 0L, TRUE) } rlist/man/list.select.Rd0000644000176200001440000000130513650064674014714 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.select.R \name{list.select} \alias{list.select} \title{Select by name or expression for each member of a list} \usage{ list.select(.data, ...) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{...}{A group of implicit labmda expressions} } \description{ Select by name or expression for each member of a list } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.select(x, type) list.select(x, tp = type) list.select(x, type, score) list.select(x, type, score.range = range(unlist(score))) } rlist/man/tryEval.Rd0000644000176200001440000000114013650064674014106 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils.R \name{tryEval} \alias{tryEval} \title{Try to evaluate an expression and return a default value if an error occurs or otherwise return its value.} \usage{ tryEval(expr, def = NULL) } \arguments{ \item{expr}{the expression to evaluate} \item{def}{the default value if an error occurs in the evaluation of \code{expr}} } \description{ Try to evaluate an expression and return a default value if an error occurs or otherwise return its value. } \examples{ x <- list(a=c(x=1,y=2),b=c(x=2,p=3)) list.map(x, tryEval(x+y, NA)) } rlist/man/contains.Rd0000644000176200001440000000054314114255253014273 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/functions.R \name{contains} \alias{contains} \title{Test if a vector contains certain values} \usage{ contains(table, x) } \arguments{ \item{table}{the values to be matched against} \item{x}{the values to be matched} } \description{ Test if a vector contains certain values } rlist/man/dot-evalwith.Rd0000644000176200001440000000064313650321110015053 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/functions.R \name{.evalwith} \alias{.evalwith} \title{Convert an object to evaluating environment for list elements Users should not directly use this function} \usage{ .evalwith(x) } \arguments{ \item{x}{the object} } \description{ Convert an object to evaluating environment for list elements Users should not directly use this function } rlist/man/args_list.Rd0000644000176200001440000000037614114255253014450 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/functions.R \name{args_list} \alias{args_list} \title{create a list for args} \usage{ args_list(...) } \arguments{ \item{...}{objects} } \description{ create a list for args } rlist/man/list.apply.Rd0000644000176200001440000000067213650064674014570 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.do.R \name{list.apply} \alias{list.apply} \title{Apply a function to each list element (\code{lapply})} \usage{ list.apply(.data, .fun, ...) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{.fun}{\code{function}} \item{...}{Additional parameters passed to \code{FUN}.} } \description{ Apply a function to each list element (\code{lapply}) } rlist/man/list.match.Rd0000644000176200001440000000131413650064674014531 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.match.R \name{list.match} \alias{list.match} \title{Select members of a list that match given regex pattern} \usage{ list.match(.data, pattern, ...) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{pattern}{\code{character}. The regex pattern to match the name of the members} \item{...}{Additional parameters to pass to \code{grep}} } \description{ Select members of a list that match given regex pattern } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.match(x,'p[12]') list.match(x,'3') } rlist/man/list.prepend.Rd0000644000176200001440000000103013650064674015065 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.insert.R \name{list.prepend} \alias{list.prepend} \title{Prepend elements to a list} \usage{ list.prepend(.data, ...) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{...}{The \code{vector} or \code{list} to prepend before \code{x}} } \description{ Prepend elements to a list } \examples{ x <- list(a=1,b=2,c=3) list.prepend(x, d=4, e=5) list.prepend(x, d=4, f=c(2,3)) } \seealso{ \code{\link{list.append}}, \code{\link{list.insert}} } rlist/man/list.iter.Rd0000644000176200001440000000120413650064674014376 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.map.R \name{list.iter} \alias{list.iter} \title{Iterate a list by evaluating an expression on each list element} \usage{ list.iter(.data, expr) } \arguments{ \item{.data}{\code{list}} \item{expr}{A lambda expression} } \value{ \code{invisible(.data)} } \description{ Iterate a list by evaluating an expression on each list element } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.iter(x,cat(paste(type,'\n'))) list.iter(x,cat(str(.))) } rlist/man/list.unzip.Rd0000644000176200001440000000446113650064674014610 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.zip.R \name{list.unzip} \alias{list.unzip} \title{Transform a list of elements with similar structure into a list of decoupled fields} \usage{ list.unzip( .data, .fields = c("intersect", "union"), ..., .aggregate = "simplify2array", .missing = NA ) } \arguments{ \item{.data}{A \code{list} of elements containing common fields} \item{.fields}{\code{'intersect'} to select only common fields for all \code{.data}'s elements. \code{'union'} to select any field that is defined in any elements in \code{.data}.} \item{...}{The custom aggregate functions. Can be a named list of functions or character vectors. If a function is specified as a list of functions, then the functions will be evaluated recursively on the result of the field. Use \code{identity} to avoid aggregating results. Use \code{NULL} to remove certain field.} \item{.aggregate}{The default aggregate function, by default, \code{simplify2array}. Can be a function, character vector or a list of functions. Use \code{identity} to avoid aggregating results.} \item{.missing}{When \code{.fields} is \code{'union'} and some elements do not contain certain fields, then \code{NULL} will be replaced by the value of \code{.missing}, by default, \code{NA}. This often makes the result more friendly.} } \description{ Transform a list of elements with similar structure into a list of decoupled fields } \examples{ list.unzip(list(p1 = list(a = 1, b = 2), p2 = list(a = 2, b = 3))) list.unzip(list(p1 = list(a = 1, b = 2), p2 = list(a = 2, b = 3, c = 4))) list.unzip(list(p1 = list(a = 1, b = 2), p2 = list(a = 2, b = 3, c = 4)), 'union') list.unzip(list(p1 = list(a = 1, b = 2), p2 = list(a = 2, b = 3, c = 4)), 'union', a = 'identity') list.unzip(list(p1 = list(a = 1, b = 2), p2 = list(a = 2, b = 3, c = 4)), 'intersect', a = NULL) x <- list(april = list(n_days = 30, holidays = list(list('2015-04-01', 'april fools'), list('2015-04-05', 'easter')), month_info = c(number = '4', season = 'spring')), july = list(n_days = 31, holidays = list(list('2014-07-04', 'july 4th')), month_info = c(number = '7', season = 'summer'))) list.unzip(x, holidays = c('list.ungroup', 'unname', 'list.stack', function(df) setNames(df, c("date", "name")))) } \seealso{ \code{\link{list.zip}} } rlist/man/args_env.Rd0000644000176200001440000000050714114255253014261 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/functions.R \name{args_env} \alias{args_env} \title{create an environment for args} \usage{ args_env(..., parent = parent.frame()) } \arguments{ \item{...}{objects} \item{parent}{parent environment} } \description{ create an environment for args } rlist/man/getnames.Rd0000644000176200001440000000117713650321110014252 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/functions.R \name{getnames} \alias{getnames} \title{Get the names of an object} \usage{ getnames(x, def = NULL) } \arguments{ \item{x}{the object to extract names} \item{def}{the value to return if the object has \code{NULL} names. For vectorization purpose, set this to \code{character(1L)}.} } \description{ Get the names of an object } \details{ This function is used in vectorization when the names of an object is to be supplied. \code{NULL} value will break the vectorization while setting \code{def = character(1L)} makes the names vectorizable. } rlist/man/list.do.Rd0000644000176200001440000000117013650064674014037 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.do.R \name{list.do} \alias{list.do} \title{Call a function with a list of arguments} \usage{ list.do(.data, fun, ...) } \arguments{ \item{.data}{\code{list}. \code{vector} will be coreced to \code{list} before being passed to \code{fun}.} \item{fun}{The \code{function} to call} \item{...}{The additional parameters passed to \code{do.call}} } \description{ Call a function with a list of arguments } \examples{ x <- lapply(1:3, function(i) { c(a=i,b=i^2)}) df <- lapply(1:3, function(i) { data.frame(a=i,b=i^2,c=letters[i])}) list.do(x, rbind) } rlist/man/list.load.Rd0000644000176200001440000000315413650064674014360 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.load.R \name{list.load} \alias{list.load} \title{Load a list from file} \usage{ list.load( file, type = tools::file_ext(file), ..., guess = c("json", "yaml", "rds", "rdata", "xml"), action = c("none", "merge", "ungroup"), progress = length(file) >= 5L ) } \arguments{ \item{file}{a \code{character} vector. The file as input.} \item{type}{The type of input which, by default, is determined by file extension. Currently supports RData, RDS, JSON, YAML.} \item{...}{Additional parameters passed to the loader function} \item{guess}{a \code{character} vector to guess iteratively if \code{type} of \code{file} is unrecognized, \code{NA} or empty string.} \item{action}{The post-processing action if multiple files are supplied. This parameter will be ignored if only a single file is supplied. \code{'none'} (default) to leave the resulted list as a list of elements corresponding to elements in \code{file} vector. \code{'merge'} to merge the list elements iteratively, the later lists always modify the former ones through \code{modifyList}. \code{'ungroup'} to ungroup the list elements, especially when each file is a page of elements with identical structure.} \item{progress}{\code{TRUE} to show a text progress bar in console while loading files. By default, if \code{file} contains 5 elements, then the progress bar will automatically be triggered to indicate loading progress.} } \description{ Load a list from file } \examples{ \dontrun{ list.load('list.rds') list.load('list.rdata') list.load('list.yaml') list.load('list.json') } } rlist/man/list.common.Rd0000644000176200001440000000152013650064674014724 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.common.R \name{list.common} \alias{list.common} \title{Get all common cases by expression for a list} \usage{ list.common(.data, expr) } \arguments{ \item{.data}{\code{list}} \item{expr}{An anonymous (or "lambda") expression to determine common cases. If one is not specified, \code{list.common} simply returns all identical sub-elements within lists.} } \description{ Get all common cases by expression for a list } \examples{ x <- list(c('a','b','c'),c('a','b'),c('b','c')) list.common(x, .) x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.common(x,type) list.common(x,names(score)) foo <- list(x = LETTERS[1:3], y = LETTERS[3:5]) list.common(foo) } rlist/man/list.skip.Rd0000644000176200001440000000110513650064674014401 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.skip.R \name{list.skip} \alias{list.skip} \title{Skip a number of elements} \usage{ list.skip(.data, n) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{n}{\code{integer}. The number of elements to skip} } \description{ Skip the first \code{n} elements of a list or vector and return the remaining elements if any. } \examples{ x <- list(a=1,b=2,c=3) list.skip(x, 1) list.skip(x, 2) } \seealso{ \code{\link{list.skipWhile}}, \code{\link{list.take}}, \code{\link{list.takeWhile}} } rlist/man/list.which.Rd0000644000176200001440000000125513650064674014543 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.which.R \name{list.which} \alias{list.which} \title{Give the indices of list elements satisfying a given condition} \usage{ list.which(.data, cond) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{cond}{A logical lambda expression} } \value{ an \code{integer} vector } \description{ Give the indices of list elements satisfying a given condition } \examples{ x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), p2 = list(type='B',score=list(c1=9,c2=9)), p3 = list(type='B',score=list(c1=9,c2=7))) list.which(x, type == 'B') list.which(x, min(score$c1,score$c2) >= 8) } rlist/man/list.search.Rd0000644000176200001440000000547613650064674014717 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/list.search.R \name{list.search} \alias{list.search} \title{Search a list recusively by an expression} \usage{ list.search(.data, expr, classes = "ANY", n, unlist = FALSE) } \arguments{ \item{.data}{A \code{list} or \code{vector}} \item{expr}{a lambda expression} \item{classes}{a character vector of class names that restrict the search. By default, the range is unrestricted (\code{ANY}).} \item{n}{the maximal number of vectors to return} \item{unlist}{\code{logical} Should the result be unlisted?} } \description{ Search a list recusively by an expression } \details{ \code{list.search} evaluates an expression (\code{expr}) recursively along a list (\code{.data}). If the expression results in a single-valued logical vector and its value is \code{TRUE}, the whole vector will be collected If it results in multi-valued or non-logical vector, the non-\code{NA} values resulted from the expression will be collected. To search whole vectors that meet certain condition, specify the expression that returns a single logical value. To search the specific values within the vectors, use subsetting in the expression, that is, \code{.[cond]} or lambda expression like \code{x -> x[cond]} where \code{cond} is a logical vector used to select the elements in the vector. } \examples{ # Exact search x <- list(p1 = list(type='A',score=c(c1=9)), p2 = list(type=c('A','B'),score=c(c1=8,c2=9)), p3 = list(type=c('B','C'),score=c(c1=9,c2=7)), p4 = list(type=c('B','C'),score=c(c1=8,c2=NA))) ## Search exact values list.search(x, identical(., 'A')) list.search(x, identical(., c('A','B'))) list.search(x, identical(., c(9,7))) list.search(x, identical(., c(c1=9,c2=7))) ## Search all equal values list.search(x, all(. == 9)) list.search(x, all(. == c(8,9))) list.search(x, all(. == c(8,9), na.rm = TRUE)) ## Search any equal values list.search(x, any(. == 9)) list.search(x, any(. == c(8,9))) # Fuzzy search data <- list( p1 = list(name='Ken',age=24), p2 = list(name='Kent',age=26), p3 = list(name='Sam',age=24), p4 = list(name='Keynes',age=30), p5 = list(name='Kwen',age=31) ) list.search(data, grepl('^K\\\\w+n$', .), 'character') \dontrun{ library(stringdist) list.search(data, stringdist(., 'Ken') <= 1, 'character') list.search(data, stringdist(., 'Man') <= 2, 'character') list.search(data, stringdist(., 'Man') > 2, 'character') } data <- list( p1 = list(name=c('Ken', 'Ren'),age=24), p2 = list(name=c('Kent', 'Potter'),age=26), p3 = list(name=c('Sam', 'Lee'),age=24), p4 = list(name=c('Keynes', 'Bond'),age=30), p5 = list(name=c('Kwen', 'Hu'),age=31)) list.search(data, .[grepl('e', .)], 'character') \dontrun{ list.search(data, all(stringdist(., 'Ken') <= 1), 'character') list.search(data, any(stringdist(., 'Ken') > 1), 'character') } } rlist/DESCRIPTION0000644000176200001440000000173014114411362013113 0ustar liggesusersPackage: rlist Type: Package Title: A Toolbox for Non-Tabular Data Manipulation Version: 0.4.6.2 Author: Kun Ren Maintainer: Kun Ren Description: Provides a set of functions for data manipulation with list objects, including mapping, filtering, grouping, sorting, updating, searching, and other useful functions. Most functions are designed to be pipeline friendly so that data processing with lists can be chained. Depends: R (>= 2.15) Date: 2021-09-02 Suggests: testthat, stringdist Imports: yaml, jsonlite, XML, data.table License: MIT + file LICENSE URL: https://renkun-ken.github.io/rlist/, https://github.com/renkun-ken/rlist, https://renkun-ken.github.io/rlist-tutorial/ BugReports: https://github.com/renkun-ken/rlist/issues ByteCompile: TRUE LazyData: true RoxygenNote: 7.1.1 Encoding: UTF-8 NeedsCompilation: no Packaged: 2021-09-02 23:36:14 UTC; ken Repository: CRAN Date/Publication: 2021-09-03 12:20:02 UTC rlist/tests/0000755000176200001440000000000013650064303012551 5ustar liggesusersrlist/tests/testthat/0000755000176200001440000000000014114411362014406 5ustar liggesusersrlist/tests/testthat/test-map.R0000644000176200001440000000352013650064303016266 0ustar liggesuserscontext("map") test_that("list.map", { # simple list x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.map(x, score$c1), list(p1 = 10, p2 = 9, p3 = 9)) # list of vectors x <- list(a = c(x = 1, y = 2), b = c(x = 3, y = 4)) expect_identical(list.map(x, sum(.)), list(a = 3, b = 7)) lapply(1:3, function(i) list.map(x, sum(.) + i)) }) test_that("list.mapv", { # simple list x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_equal(list.mapv(x, score$c1), c(p1 = 10, p2 = 9, p3 = 9)) expect_equal(list.mapv(x, x ~ sum(unlist(x$score))), c(p1 = 18, p2 = 18, p3 = 16)) expect_identical(list.mapv(x, score$c1, "integer"), c(p1 = 10L, p2 = 9L, p3 = 9L)) expect_identical(list.mapv(x, score$c1, "integer", use.names = FALSE), c(10L, 9L, 9L)) # list of vectors x <- list(a = c(x = 1, y = 2), b = c(x = 3, y = 4)) expect_equal(list.mapv(x, sum(.)), c(a = 3, b = 7)) lapply(1:3, function(i) list.mapv(x, sum(.) + i)) }) test_that("list.iter", { l1 <- list(1, 2, 3) expect_output(list.iter(l1, cat(.)), "123") expect_equal(list.iter(l1, { }), l1) }) test_that("list.maps", { l1 <- list(p1 = list(x = 1, y = 2), p2 = list(x = 3, y = 4), p3 = list(x = 1, y = 3)) l2 <- list(2, 3, 5) expect_equal(list.maps(a$x * b + a$y, a = l1, b = l2), list(p1 = 4, p2 = 13, p3 = 8)) expect_equal(list.maps(..1$x * ..2 + ..1$y, l1, l2), list(p1 = 4, p2 = 13, p3 = 8)) expect_equal(list.maps(a * b, a = list(1, 2, 3), b = list(2, 3, 4)), list(2, 6, 12)) expect_equal(list.maps(..1 * ..2, list(1, 2, 3), list(2, 3, 4)), list(2, 6, 12)) }) rlist/tests/testthat/test-search.R0000644000176200001440000000612214114255253016761 0ustar liggesuserscontext("search") test_that("list.search", { # logical search x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.search(x, identical(., "A")), list(p1.type = "A")) expect_identical(list.search(x, identical(., "A"), unlist = TRUE), c(p1.type = "A")) expect_identical(list.search(x, identical(., 9)), list(p2.score.c1 = 9, p2.score.c2 = 9, p3.score.c1 = 9)) x <- list(p1 = list(x = c("A", "B", "C"), y = list(y1 = "A", y2 = c("B", "C"))), p2 = list(a = c("A", "B"), b = list(b1 = c("B", "C"), b2 = list("C", "B")))) expect_identical(list.search(x, all(. == "A")), list(p1.y.y1 = "A")) expect_identical(list.search(x, any("A" %in% .)), list(p1.x = c("A", "B", "C"), p1.y.y1 = "A", p2.a = c("A", "B"))) # fuzzy search x <- list(p1 = list(name = "Ken", age = 24), p2 = list(name = "Kent", age = 26), p3 = list(name = "Sam", age = 24), p4 = list(name = "Keynes", age = 30), p5 = list(name = "Kwen", age = 31)) expect_equal(list.search(x, grepl("^K\\w+[ts]", .), "character", unlist = TRUE), c(p2.name = "Kent", p4.name = "Keynes")) y <- list(n = 1:10, list(df = data.frame(id = 1:10, letter = letters[1:10], stringsAsFactors = F)), list("aa", "bb")) expect_identical(list.search(y, .[grepl("a", .)], "character"), list(df.letter = "a", "aa")) expect_error(list.search(y, . <= p)) }) test_that("stringdist", { skip_if_not_installed("stringdist") x <- list(p1 = list(name = "Ken", age = 24), p2 = list(name = "Kent", age = 26), p3 = list(name = "Sam", age = 24), p4 = list(name = "Keynes", age = 30), p5 = list(name = "Kwen", age = 31)) expect_equal(list.search(x, any(stringdist::stringdist(., "Ken") <= 1), "character", unlist = TRUE), c(p1.name = "Ken", p2.name = "Kent", p5.name = "Kwen")) expect_identical(list.search(x, all(stringdist::stringdist(., "Ken") == 0), "character"), list(p1.name = "Ken")) x <- list(p1 = list(name = c("Ken", "Ren"), age = 24), p2 = list(name = c("Kent", "Potter"), age = 26), p3 = list(name = c("Sam", "Lee"), age = 24), p4 = list(name = c("Keynes", "Bond"), age = 30), p5 = list(name = c("Kwen", "Hu"), age = 31)) expect_equal(list.search(x, all(stringdist::stringdist(., "Ken") <= 1), "character"), list(p1.name = c("Ken", "Ren"))) expect_equal(list.search(x, any(stringdist::stringdist(., "Ken") <= 1), "character"), list(p1.name = c("Ken", "Ren"), p2.name = c("Kent", "Potter"), p5.name = c("Kwen", "Hu"))) expect_equal(list.search(x, !any(stringdist::stringdist(., "Ken") <= 1), "character"), list(p3.name = c("Sam", "Lee"), p4.name = c("Keynes", "Bond"))) }) test_that("counting", { x <- list(p1 = list(name = "Ken", age = 24), p2 = list(name = "Kent", age = 26), p3 = list(name = "Sam", age = 24), p4 = list(name = "Keynes", age = 30), p5 = list(name = "Kwen", age = 31)) expect_equal(list.search(x, n ~ n >= 25, "numeric", n = 2, unlist = TRUE), c(p2.age = 26, p4.age = 30)) expect_error(list.search(x, . <= p)) }) rlist/tests/testthat/test-sort.R0000644000176200001440000000336713650064303016511 0ustar liggesuserscontext("sort") test_that("list.sort", { # simple list x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.sort(x, type, (score$c2)), x[c(1, 2, 3)]) expect_identical(list.sort(x, min(score$c1, score$c2)), x[c(3, 1, 2)]) # list of vectors x <- list(a = c(x = 1, y = 2), b = c(x = 3, y = 4)) expect_identical(list.sort(x, sum(.)), x[c(1, 2)]) expect_identical(list.sort(x, (sum(.))), x[c(2, 1)]) expect_identical(list.sort(c("a", "b", "c")), c("a", "b", "c")) expect_identical(list.sort(c("a", "b", "c"), (.)), c("c", "b", "a")) expect_identical(list.sort(list("a", "b", "c"), .), list("a", "b", "c")) expect_identical(list.sort(list("a", "b", "c"), (.)), list("c", "b", "a")) # warning in irregular cases expect_warning(list.sort(list(1, 2, c(2, 3)), .), "^Non-single value in column") expect_warning(list.sort(list(1, 2, "a"), .), "^Inconsistent classes") lapply(1:3, function(i) list.sort(x, sum(.) + i)) }) test_that("list.order", { x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_equal(list.order(x, type, (score$c2)), c(1, 2, 3)) expect_equal(list.order(x, min(score$c1, score$c2)), c(3, 1, 2)) x <- list(a = c(x = 1, y = 2), b = c(x = 3, y = 4)) expect_equal(lapply(1:3, function(i) list.order(x, sum(.) + i)), list(c(1, 2), c(1, 2), c(1, 2))) # warning in irregular cases expect_warning(list.order(list(1, 2, c(2, 3)), .), "^Non-single value in column") expect_warning(list.order(list(1, 2, "a"), .), "^Inconsistent classes") }) rlist/tests/testthat/test-group.R0000644000176200001440000000441513650064303016651 0ustar liggesuserscontext("group") test_that("list.group", { # simple list x <- list(a = 1, b = 2, c = 3, d = 2, e = 3, f = 1) expect_identical(list.group(x, .), list(`1` = list(a = 1, f = 1), `2` = list(b = 2, d = 2), `3` = list(c = 3, e = 3))) x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.group(x, type), list(A = x["p1"], B = x[c("p2", "p3")])) expect_identical(list.group(x, mean(unlist(score))), list(`8` = x["p3"], `9` = x[c("p1", "p2")])) expect_identical(list.group(1:10, . %% 3, . %% 2), structure(list(`0` = structure(list(`0` = 6L, `1` = c(3L, 9L)), .Names = c("0", "1")), `1` = structure(list(`0` = c(4L, 10L), `1` = c(1L, 7L)), .Names = c("0", "1")), `2` = structure(list(`0` = c(2L, 8L), `1` = 5L), .Names = c("0", "1"))), .Names = c("0", "1", "2"))) expect_identical(list.group(c(3, 1, 3, 3, 2, 2), letters[.], sorted = FALSE), list(c = c(3, 3, 3), a = 1, b = c(2, 2))) expect_identical(list.group(c(3, 1, 3, 3, 2, 2), letters[.], sorted = TRUE), list(a = 1, b = c(2, 2), c = c(3, 3, 3))) # test dynamic scoping lapply(2:4, function(i) list.group(x, sum(unlist(score)) <= i)) }) test_that("list.ungroup", { xg <- list(`1` = list(a = 1, f = 1), `2` = list(b = 2, d = 2), `3` = list(c = 3, e = 3)) xg2 <- list(a = list(a = 1, f = 1), c = list(b = 2, d = 2), b = list(c = 3, e = 3)) expect_identical(list.ungroup(xg, sort.names = TRUE), list(a = 1, b = 2, c = 3, d = 2, e = 3, f = 1)) expect_identical(list.ungroup(xg2, sort.names = FALSE), list(a = 1, f = 1, b = 2, d = 2, c = 3, e = 3)) x <- list(a = list(a1 = list(x=list(x1=2,x2=3),y=list(y1=1,y2=3)), a0 = list(x=list(x1=1,x2=5),y=list(y1=0,y2=1))), b = list(b1 = list(x=list(x1=2,x2=6),y=list(y1=3,y2=2)))) expect_identical(list.ungroup(x, level = 1L), c(x$a, x$b)) expect_identical(list.ungroup(x, level = 2L), c(unlist(unname(x$a), recursive = FALSE), unlist(unname(x$b), recursive = FALSE))) expect_identical(list.ungroup(x, level = 1L, group.names = TRUE), unlist(x, recursive = FALSE)) expect_identical(list.ungroup(x, level = 2L, group.names = TRUE), c(unlist(unlist(x, recursive = FALSE), recursive = FALSE))) }) rlist/tests/testthat/test-internal.R0000644000176200001440000000035513650064303017330 0ustar liggesuserscontext("internal") test_that("internal", { e <- list2env(list(a = 1), parent = emptyenv()) expect_error(try_list(expression(symbol1, symbol2), envir = e)) expect_equal(try_list(expression(symbol1, symbol2), 0, envir = e), 0) }) rlist/tests/testthat/test-List.R0000644000176200001440000000553113650064303016430 0ustar liggesuserscontext("List") test_that("List", { x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical({ List(x)$group(type)$map(g ~ List(g)$map(score)$call(unlist)$call(mean)$data)$data }, list(A = 9, B = 8.5)) expect_identical({ local({ i <- 3 List(1:3)$map(x ~ x + i)[] }) }, list(4, 5, 6)) expect_identical({ local({ i <- 1 List(1:3)$map(x ~ x + i)$filter(x ~ x <= 1 + i)[] }) }, list(2)) expect_identical(List(1:3)$all(. >= 0)[], TRUE) expect_identical(List(1:3)$any(. <= 5)[], TRUE) expect_identical(List(x)$cases(type)[], c("A", "B")) expect_identical(List(x)$class(type)[], list.class(x, type)) expect_identical(List(x)$common(names(score))[], c("c1", "c2")) expect_identical(List(x)$count(type == "B")[], 2L) expect_identical(List(x)$filter(type == "B")[], list.filter(x, type == "B")) expect_identical(List(1:10)$find(.%%2 == 0, 3)[], c(2L, 4L, 6L)) expect_identical(List(1:10)$findi(.%%2 == 0, 3)[], c(2L, 4L, 6L)) expect_identical(List(1:10)$group(.%%3)[], list.group(1:10, .%%3)) expect_identical(List(list(1:10, 2:15))$search(any(. >= 11))[], list.search(list(1:10, 2:15), any(. >= 11))) expect_identical(local({ i <- 12 List(list(1:10, 2:15))$search(any(. >= i))[] }), list.search(list(1:10, 2:15), any(. >= 12))) expect_identical(List(1:200)$table(.%%2, .%%3)[], list.table(1:200, .%%2, .%%3)) expect_identical(List(x)$update(mean = mean(unlist(score)))[], list.update(x, mean = mean(unlist(score)))) expect_equal(List(c(1, 2, 3)) == c(1, 2, 3), c(TRUE, TRUE, TRUE)) expect_equal(subset(List(1:10), c(TRUE, FALSE)), subset(1:10, c(TRUE, FALSE))) }) test_that("closure", { expect_is(List_get_function(quote(`[`)), "function") expect_is(List_set_function(quote(`[`)), "function") }) test_that("subsetting", { expect_identical(List(list(a = 1, b = 2))["a"]$data, list(a = 1)) expect_equal(List(c(a = 1, b = 2))["a"]$data, c(a = 1)) }) test_that("extracting", { expect_equal(List(list(a = 1, b = 2))[["a"]]$data, 1) expect_equal(List(list2env(list(a = 1, b = 2)))[["a"]]$data, 1) }) test_that("assignment", { expect_identical({ z <- List(list(a = 1, b = 2)) z$a <- 2 z$b <- NULL z$data }, list(a = 2)) expect_equal({ z <- new.env() env <- List(z) env$a <- 1 env$data$a }, 1) expect_identical({ z <- List(c(a = 1, b = 2)) z["a"] <- 2 z$data }, c(a = 2, b = 2)) expect_identical({ z <- List(c(a = 1, b = 2)) z[["a"]] <- 2 z$data }, c(a = 2, b = 2)) }) test_that("printing", { expect_output(print(List(list(1, 2, 3))), "\\$data : list.+") expect_output(str(List(list(1, 2, 3))), "\\$data : List of 3.+") expect_output(print(summary(List(rnorm(100)))), "Min.+") }) rlist/tests/testthat/test-filter.R0000644000176200001440000000226713650064303017005 0ustar liggesuserscontext("filter") test_that("list.is", { x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.is(x, type == "B"), unlist(lapply(x, function(item) item$type == "B"))) l1 <- list(a = list(x = 1, y = 2), b = list(x = 2, y = 3)) expect_identical(lapply(2:4, function(i) list.is(l1, sum(unlist(.)) <= i)), list(c(a = FALSE, b = FALSE), c(a = TRUE, b = FALSE), c(a = TRUE, b = FALSE))) }) test_that("list.filter", { # simple list x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.filter(x, type == "B"), x[c(2, 3)]) # list of vectors x <- list(a = c(x = 1, y = 2), b = c(x = 3, y = 4)) expect_identical(list.filter(x, sum(.) >= 4), x["b"]) # list of lists l1 <- list(a = list(x = 1, y = 2), b = list(x = 2, y = 3)) expect_identical(list.filter(l1, sum(unlist(.)) <= 4), l1["a"]) # test dynamic scoping lapply(2:4, function(i) list.filter(l1, sum(unlist(.)) <= i)) }) rlist/tests/testthat/test-update.R0000644000176200001440000000151113650064303016771 0ustar liggesuserscontext("update") test_that("list.update", { # simple list x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.update(x, type = NULL), lapply(x, function(xi) { xi[-1] })) expect_identical(list.update(x, score = list(min = min(unlist(score)))), lapply(x, function(xi) { modifyList(xi, list(score = list(min = min(unlist(xi$score))))) })) expect_identical(list.update(x, range = range(unlist(score))), lapply(x, function(xi) { modifyList(xi, list(range = range(unlist(xi$score)))) })) expect_identical(list.update(x, n = length(.)), lapply(x, function(xi) { modifyList(xi, list(n = length(xi))) })) lapply(1:3, function(i) list.update(x, c = i)) }) rlist/tests/testthat/test-join.R0000644000176200001440000000134213650064303016450 0ustar liggesuserscontext("join") test_that("list.join", { l1 <- list(p1 = list(name = "Ken", age = 20), p2 = list(name = "James", age = 21), p3 = list(name = "Jenny", age = 20)) l2 <- list(p1 = list(name = "Jenny", age = 20, type = "A"), p2 = list(name = "Ken", age = 20, type = "B"), p3 = list(name = "James", age = 21, type = "A")) l3 <- list(p1 = list(name = "Ken", age = 20, type = "B"), p2 = list(name = "James", age = 21, type = "A"), p3 = list(name = "Jenny", age = 20, type = "A")) expect_identical(list.join(l1, l2, name), l3) expect_identical(list.join(l1, l2, .[c("name", "age")]), l3) expect_identical(list.join(l1, l2, .[c("name", "age")], .[c("name", "age")]), l3) expect_error(list.join(l1, l2, name, age)) }) rlist/tests/testthat/test-select.R0000644000176200001440000000134513650064303016773 0ustar liggesuserscontext("select") test_that("list.select", { # simple list x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.select(x, type), lapply(x, function(xi) { xi["type"] })) expect_identical(list.select(x, type, score), lapply(x, function(xi) { xi[c("type", "score")] })) expect_identical(list.select(x, range = range(unlist(score))), lapply(x, function(xi) { list(range = range(unlist(xi$score))) })) expect_identical(list.select(x, n = length(.)), lapply(x, function(xi) { list(n = length(xi)) })) lapply(1:3, function(i) list.select(x, p = score$c1 + i)) }) rlist/tests/testthat/test-class.R0000644000176200001440000000114113650064303016613 0ustar liggesuserscontext("class") test_that("list.class", { # simple list x <- list(a = 1, b = 2, c = 3, d = 2, e = 3, f = 1) expect_identical(list.class(x, .), list(`1` = list(a = 1, f = 1), `2` = list(b = 2, d = 2), `3` = list(c = 3, e = 3))) x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.class(x, unlist(score)), list(`7` = x["p3"], `8` = x["p1"], `9` = x[c("p2", "p3")], `10` = x["p1"])) lapply(8:10, function(i) list.class(x, score$c1 > i)) }) rlist/tests/testthat/test-io.R0000644000176200001440000000347313650064303016127 0ustar liggesuserscontext("io") test_that("list.serialize", { x <- list(a = 1, b = 2, c = 3, d = list(x = 1, y = 2)) f <- tempfile(fileext = ".json") expect_identical(list.serialize(x, f), x) expect_identical(list.unserialize(f), x) file.remove(f) f <- tempfile() expect_identical(list.serialize(x, f), x) expect_identical(list.unserialize(f), x) file.remove(f) }) test_that("list.save, list.load", { x <- list(a = 1, b = 2, c = 3, d = list(x = 1, y = c(1, 2, 3))) f <- tempfile(fileext = ".json") expect_equal(list.save(x, file = f), x) expect_equal(list.load(f), x) file.remove(f) f <- tempfile(fileext = ".yaml") expect_equal(list.save(x, file = f), x) expect_equal(list.load(f), x) file.remove(f) f <- tempfile(fileext = ".rds") expect_equal(list.save(x, file = f), x) expect_equal(list.load(f), x) file.remove(f) f <- tempfile(fileext = ".rdata") expect_equal(list.save(x, file = f), x) expect_equal(list.load(f), x) file.remove(f) f <- tempfile(fileext = ".xml") writeLines("1", f) expect_equal(list.load(f), list(a = "1")) file.remove(f) # guess f <- tempfile() expect_equal(list.save(x, file = f, type = "yaml"), x) expect_equal(list.load(f), x) file.remove(f) f <- tempfile() expect_error(list.save(x, file = f, type = "unsupported_file_type")) f <- tempfile() expect_error(list.load(f, "unsupported_file_type")) n <- 3 fs <- vapply(seq_len(n), function(i) tempfile(fileext = ".json"), character(1L)) ds <- lapply(seq_len(n), function(i) list(a = i, b = i + 1L)) Map(function(d, f) { list.save(d, f) }, ds, fs) expect_equal(unname(list.load(fs)), ds) expect_equal(list.load(fs, action = "ungroup"), list.ungroup(lapply(fs, list.load))) expect_equal(list.load(fs, action = "merge"), do.call("list.merge", ds)) file.remove(fs) }) rlist/tests/testthat/test-utils.R0000644000176200001440000000115113650064303016647 0ustar liggesuserscontext("utils") test_that("tryGet", { e <- new.env() e$x <- 1 expect_identical(tryGet(x, 0, envir = e), e$x) expect_identical(with(e, tryGet(x, 0)), e$x) expect_identical(tryGet(y, 0), 0) expect_error(tryGet(y + 1, 0)) expect_identical(list.map(list(list(a = 1, b = 2), list(a = 1, c = 2)), a + tryGet(b, 0) + tryGet(c, 0)), list(3, 3)) }) test_that("tryEval", { e <- new.env() e$x <- 1 expect_identical(with(e, tryEval(x, 0)), e$x) expect_identical(tryEval(y, 0), 0) expect_identical(list.map(list(list(a = 1, b = 2), list(a = 1, c = 2)), tryEval(a + b + c, 0)), list(0, 0)) }) rlist/tests/testthat/test-basic.R0000644000176200001440000003506213650064303016600 0ustar liggesuserscontext("basic") test_that("list.append", { # atomic vector expect_identical(list.append(c(1, 2, 3), 4, 5), c(1, 2, 3, 4, 5)) expect_identical(list.append(c(a = 1, b = 2), c = 3), c(a = 1, b = 2, c = 3)) # simple list x <- list(a = 1, b = 2) expect_identical(list.append(x, c = 3), c(x, c = 3)) expect_identical(lapply(1:2, function(i) list.append(x, d = i)), lapply(1:2, function(i) c(x, d = i))) x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) p4 <- list(type = "A", score = list(c1 = 10, ce = 6)) expect_identical(list.append(x, p4 = p4), c(x, p4 = list(p4))) }) test_that("list.prepend", { # atomic vector expect_identical(list.prepend(c(1, 2, 3), 4, 5), c(4, 5, 1, 2, 3)) expect_identical(list.prepend(c(a = 1, b = 2), c = 3), c(c = 3, a = 1, b = 2)) # simple list x <- list(a = 1, b = 2) expect_identical(list.prepend(x, c = 3), c(c = 3, x)) expect_identical(lapply(1:2, function(i) list.prepend(x, d = i)), lapply(1:2, function(i) c(list(d = i), x))) x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) p0 <- list(type = "A", score = list(c1 = 10, ce = 6)) expect_identical(list.prepend(x, p0 = p0), c(p0 = list(p0), x)) }) test_that("list.insert", { expect_identical(list.insert(c(1, 2, 3), 2, 0), c(1, 0, 2, 3)) x <- list(a = 1, b = 2, c = 3) expect_identical(list.insert(x, 2, q = 0), list(a = 1, q = 0, b = 2, c = 3)) expect_identical(lapply(1:2, function(i) list.insert(x, 2, q = i)), lapply(1:2, function(i) list(a = 1, q = i, b = 2, c = 3))) }) test_that("list.extract", { # simple list x <- list(a = 1, b = 2, c = 3) expect_identical(list.extract(x, 1), x[[1]]) expect_identical(list.extract(x, "a"), x[["a"]]) expect_identical(lapply(1:2, function(i) list.extract(x, i)), lapply(1:2, function(i) x[[i]])) }) test_that("list.subset", { x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.subset(x, c("p1", "p2")), x[c("p1", "p2")]) expect_identical(list.subset(x, grepl("^p", names(x))), x[]) }) test_that("list.count", { # simple list x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_equal(list.count(x, type == "B"), 2) expect_equal(list.count(x, score$c1 < 10), 2) expect_equal(lapply(c(8, 9, 10), function(i) list.count(x, score$c1 <= i)), list(0, 2, 3)) # list of vectors x <- list(a = c(x = 1, y = 2), b = c(x = 3, y = 4)) expect_equal(list.count(x, sum(.) >= 3), 2) expect_equal(list.count(x, mean(.) >= 3), 1) }) test_that("list.reverse", { # simple list x <- list(a = 1, b = 2, c = 3) expect_identical(list.reverse(x), x[c(3, 2, 1)]) x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.reverse(x), x[c(3, 2, 1)]) }) test_that("list.merge", { # simple list x <- list(a = 1, b = 2, c = list(x = 1, y = 2)) expect_identical(list.merge(x, list(b = 5)), list(a = 1, b = 5, c = list(x = 1, y = 2))) expect_identical(list.merge(x, list(c = list(z = 3))), list(a = 1, b = 2, c = list(x = 1, y = 2, z = 3))) # multiple lists l1 <- list(a = 1, b = list(x = 1, y = 1)) l2 <- list(a = 2, b = list(z = 2)) l3 <- list(a = 2, b = list(x = 3)) expect_identical(list.merge(l1, l2, l3), modifyList(modifyList(l1, l2), l3)) }) test_that("list.do", { expect_equal(list.do(list(1, 2, 3), sum), sum(1:3)) expect_equal(list.do(list(1, 2, 3), "sum"), sum(1:3)) }) test_that("list.apply", { expect_identical(list.apply(c(1, 2, 3), "+", 1), list(2, 3, 4)) expect_identical(list.apply(c(1, 2, 3), `+`, 1), list(2, 3, 4)) }) test_that("list.rbind", { x <- lapply(1:10, function(i) c(a = i, b = i^2)) expect_identical(list.rbind(x), do.call(rbind, x)) }) test_that("list.cbind", { x <- list(data.frame(a = rnorm(10), b = rnorm(10)), data.frame(c = rnorm(10), d = rnorm(10)), data.frame(e = rnorm(10), f = rnorm(10))) expect_identical(list.cbind(x), do.call(cbind, x)) }) test_that("list.stack", { x <- lapply(1:10, function(i) list(a = i, b = i^2)) expect_false(is.null(list.stack(x))) x <- lapply(1:10, function(i) list(a = c(i, i + 1), b = c(i^2, i^2 + 1))) expect_false(is.null(list.stack(x))) }) test_that("list.match", { # simple list x <- list(a = 1, b = 2) expect_identical(list.match(x, "a"), x["a"]) expect_identical(list.match(x, "[ab]"), x) x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.match(x, "p[12]"), x[c("p1", "p2")]) }) test_that("list.take, list.skip", { # simple list x <- list(a = 1, b = 2) expect_identical(list.take(x, 1), x[1]) expect_identical(list.take(x, 0), x[0]) expect_identical(list.take(x, -1), x[-1]) expect_identical(list.skip(x, 1), x[2]) expect_identical(list.skip(x, 0), x) expect_identical(list.skip(x, -1), x[1]) }) test_that("list.takeWhile, list.skipWhile", { # simple list x <- list(a = 1, b = 2) expect_identical(list.takeWhile(x, . <= 1), x[1]) expect_equal(length(list.takeWhile(x, . >= 3)), 0) lapply(1:3, function(i) list.takeWhile(x, . <= i)) expect_error(list.takeWhile(x, . >= p)) expect_identical(list.skipWhile(x, . <= 1), x[2]) expect_equal(length(list.skipWhile(x, . >= 3)), 0) lapply(1:3, function(i) list.skipWhile(x, . <= i)) expect_error(list.skipWhile(x, . >= p)) }) test_that("list.remove", { x <- list(a = 1, b = 2) expect_identical(list.remove(x, c(FALSE, TRUE)), x[1]) expect_identical(list.remove(x, 1), x[2]) expect_identical(list.remove(x, "b"), x["a"]) expect_identical(list.remove(x, c("a", "b")), x[0]) }) test_that("list.exclude", { x <- list(a = 1, b = 2) expect_identical(list.exclude(x, . >= 2), x[1]) }) test_that("list.sample", { x <- list(a = 1, b = 2, c = 3) expect_equal(length(list.sample(x, 2, weight = .)), 2) lapply(1:2, function(n) list.sample(x, n)) }) test_that("list.cases", { x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_equal(list.cases(x, type, sort = T), c("A", "B")) expect_equal(list.cases(x, mean(unlist(score))), c(8, 9)) expect_equal(lapply(c("A", "B"), function(i) list.cases(x, type == i)), list(c(FALSE, TRUE), c(FALSE, TRUE))) x <- list(x = LETTERS[1:3], y = LETTERS[3:5]) expect_equal(list.cases(x), Reduce(union, x)) }) test_that("list.common", { x <- list(c("a", "b", "c"), c("a", "b"), c("b", "c")) expect_equal(list.common(x, .), c("b")) x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_equal(list.common(x, names(.)), c("type", "score")) expect_equal(list.common(x, names(score)), c("c1", "c2")) x <- list(x = LETTERS[1:3], y = LETTERS[3:5]) expect_equal(list.common(x), Reduce(intersect, x)) }) test_that("list.all", { x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_equal(list.all(x, type == "B"), FALSE) expect_equal(list.all(x, mean(unlist(score)) >= 6), TRUE) expect_equal(sapply(8:10, function(i) list.all(x, score$c1 >= i)), c(TRUE, TRUE, FALSE)) expect_equal(list.all(logical()), all()) expect_equal(list.all(logical(), na.rm = TRUE), all(na.rm = TRUE)) expect_equal(list.all(c(TRUE, NA, TRUE)), all(c(TRUE, NA, TRUE))) expect_equal(list.all(c(TRUE, NA, FALSE)), all(c(TRUE, NA, FALSE))) expect_equal(list.all(c(TRUE, NA, TRUE), na.rm = TRUE), all(c(TRUE, NA, TRUE), na.rm = TRUE)) expect_equal(list.all(c(TRUE, NA, FALSE), na.rm = TRUE), all(c(TRUE, NA, FALSE), na.rm = TRUE)) expect_equal(list.all(list(c(1,2,3),c(2,3,4)), . <= 3, na.rm = FALSE), NA) expect_equal(list.all(list(1,-2,10), x ~ x > 0), FALSE) expect_equal(list.all(list(1,-2,10), x ~ x + 10 > 0), TRUE) expect_error(list.all(list(1,2,3), . > p)) }) test_that("list.any", { x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_equal(list.any(x, type == "B"), TRUE) expect_equal(list.any(x, mean(unlist(score)) >= 20), FALSE) expect_equal(sapply(8:10, function(i) list.any(x, score$c1 >= i)), c(T, T, T)) expect_equal(list.any(logical()), any()) expect_equal(list.any(logical(), na.rm = TRUE), any(na.rm = TRUE)) expect_equal(list.any(c(TRUE, NA, TRUE)), any(c(TRUE, NA, TRUE))) expect_equal(list.any(c(TRUE, NA, FALSE)), any(c(TRUE, NA, FALSE))) expect_equal(list.any(c(TRUE, NA, TRUE), na.rm = TRUE), any(c(TRUE, NA, TRUE), na.rm = TRUE)) expect_equal(list.any(c(TRUE, NA, FALSE), na.rm = TRUE), any(c(TRUE, NA, FALSE), na.rm = TRUE)) expect_equal(list.any(list(1,-2,10), x ~ x > 0), TRUE) expect_equal(list.any(list(1,-2,10), x ~ x - 10 > 0), FALSE) expect_error(list.any(list(1,2,3), . > p)) }) test_that("list.first", { x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_equal(list.first(x, type == "B"), x[[2L]]) expect_equal(list.first(x, unlist(score$c1 <= 9)), x[[2L]]) expect_identical(list.first(x, score$c1 < 9 || score$c3 >= 5), NULL) expect_equal(list.first(c(NA, NA, 1), . <= 1), 1) expect_error(list.first(list(1,2,3), . > p)) }) test_that("list.last", { x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_equal(list.last(x, type == "B"), x[[3L]]) expect_equal(list.last(x, unlist(score$c1 <= 9)), x[[3L]]) expect_identical(list.last(x, score$c1 < 9 || score$c3 >= 5), NULL) expect_error(list.last(list(1,2,3), . > p)) }) test_that("list.table", { x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) x.types <- c("A", "B", "B") x.c1 <- c(10, 9, 9) expect_identical(list.table(x, type), table(type = x.types)) expect_identical(list.table(x, type, c1 = score$c1), table(type = x.types, c1 = x.c1)) x <- list(list(a = 1, b = NULL), list(a = 2, b = 1), list(a = 3, b = 1)) expect_identical(as.integer(list.table(x, a, b)), c(0L, 1L, 1L, 1L, 0L, 0L)) }) test_that("list.zip", { a <- list(1, 2) b <- list("a", "b") expect_identical(list.zip(a, b), list(list(a = 1, b = "a"), list(a = 2, b = "b"))) }) test_that("list.unzip", { x <- list(p1 = list(a = 1, b = 5), p2 = list(a = 2, b = 3)) x1 <- list(p1 = list(a = 1, b = 5), p2 = list(a = 2, b = 3, c = 4)) expect_identical(list.unzip(x), list(a = c(p1 = 1, p2 = 2), b = c(p1 = 5, p2 = 3))) expect_identical(list.unzip(x1, .fields = "union"), list(a = c(p1 = 1, p2 = 2), b = c(p1 = 5, p2 = 3), c = c(p1 = NA, p2 = 4))) expect_identical(list.unzip(x, a = "identity"), list(a = list(p1 = 1, p2 = 2), b = c(p1 = 5, p2 = 3))) expect_identical(list.unzip(x, a = NULL), list(b = c(p1 = 5, p2 = 3))) }) test_that("list.flatten", { p <- list(a = 1, b = list(b1 = 2, b2 = 3), c = list(c1 = list(c11 = "a", c12 = "x"), c2 = 3)) q <- list(a = c(1, 2, 3), b = list(x = 1, y = list(z = 1, z2 = 2))) expect_identical(list.flatten(p), list(a = 1, b.b1 = 2, b.b2 = 3, c.c1.c11 = "a", c.c1.c12 = "x", c.c2 = 3)) expect_identical(list.flatten(q), list(a = c(1, 2, 3), b.x = 1, b.y.z = 1, b.y.z2 = 2)) p <- list(a=1,b=list(x="a",y="b",z=10)) expect_identical(list.flatten(p), list(a=1, b.x = "a", b.y = "b", b.z = 10)) expect_identical(list.flatten(p, classes = "numeric"), list(a = 1, b.z = 10)) expect_identical(list.flatten(p, classes = "character"), list(b.x = "a", b.y = "b")) expect_identical(list.flatten(p, classes = "integer"), list()) expect_identical(list.flatten(p, use.names = FALSE), list(1, "a", "b", 10)) }) test_that("list.names", { expect_identical(list.names(list(a = 1, b = 2)), c("a", "b")) expect_identical(list.names(list(1, 2)), NULL) expect_identical(list.names(list(1, 2), letters[.]), list(a = 1, b = 2)) expect_identical(list.names(list(a = 1, b = 2), NULL), list(1, 2)) }) test_that("list.parse", { expect_identical(list.parse(c(a = 1)), list(a = 1)) expect_identical({ mat <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 3) rownames(mat) <- c("a", "b", "c") colnames(mat) <- paste0("V", 1:2) list.parse(mat) }, list(a = list(V1 = 1, V2 = 4), b = list(V1 = 2, V2 = 5), c = list(V1 = 3, V2 = 6))) expect_identical(list.parse("hello"), list("hello")) expect_identical(list.parse(data.frame(x = c(1, 2), y = c(2, 3))), list(`1` = list(x = 1, y = 2), `2` = list(x = 2, y = 3))) expect_equal(list.parse("a: 1", "yaml"), list(a = 1)) expect_equal(list.parse("{ \"a\": 1, \"b\": 2 }", "json"), list(a = 1, b = 2)) expect_equal(list.parse("12", "xml"), list(a = "1", b = "2")) expect_error(list.parse("a:1,b:2", "js"), "Unsupported type of data") expect_equal(list.parse(c("a: 1", "{ \"a\": 1, \"b\": 2 }"), c("yaml", "json")), list(list(a = 1), list(a = 1, b = 2))) }) test_that("list.clean", { expect_identical(list.clean(list(1, 2, NULL)), list(1, 2)) expect_identical(list.clean(list(1, 2, NA), is.na), list(1, 2)) expect_identical(list.clean(list(1, 2, numeric(), list(1, 2, NULL)), function(x) length(x) == 0L, recursive = TRUE), list(1, 2, list(1, 2))) expect_identical(list.clean(list(1, 2, list(1, 2, NULL), NULL), recursive = TRUE), list(1, 2, list(1, 2))) }) test_that("list.which", { x <- c(1, 2, 3) expect_identical(list.which(x, . >= 2), which(x >= 2)) }) test_that("list.expand", { expect_identical(list.expand(), list()) expect_identical(list.expand(x = integer()), list()) expect_identical(list.expand(x = 1:3, y = integer()), list()) expect_identical(list.expand(x = c(1,2), y = c(2,3)), list(list(x = 1, y = 2), list(x = 2, y = 2), list(x = 1, y = 3), list(x = 2, y = 3))) }) rlist/tests/testthat/test-find.R0000644000176200001440000000172613650064303016437 0ustar liggesuserscontext("find") test_that("list.findi", { x <- list(1, 2, c(3, 4)) expect_identical(list.findi(x, any(. >= 2)), 2L) expect_identical(list.findi(x, any(. >= 2), 2), c(2L, 3L)) expect_identical(list.findi(x, any(. >= 2), 3), c(2L, 3L)) expect_identical(list.findi(x, any(. >= 2), 4), c(2L, 3L)) }) test_that("list.find", { # simple list x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(list.find(x, type == "B", 1), x[2]) expect_identical(list.find(x, type == "B", 2), x[c(2, 3)]) # list of vectors x <- list(a = c(x = 1, y = 2), b = c(x = 3, y = 4)) expect_identical(list.find(x, sum(.) >= 4), x[2]) # list of lists l1 <- list(a = list(x = 1, y = 2), b = list(x = 2, y = 3)) expect_identical(list.find(l1, sum(unlist(.)) <= 4), l1[1]) lapply(2:4, function(i) list.find(l1, sum(unlist(.)) <= i)) }) rlist/tests/testthat/test-subset.R0000644000176200001440000000357413650064303017027 0ustar liggesuserscontext("subset") test_that("subset.list", { # simple list x <- list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(type = "B", score = list(c1 = 9, c2 = 9)), p3 = list(type = "B", score = list(c1 = 9, c2 = 7))) expect_identical(subset(x, type == "B"), x[c(2, 3)]) expect_identical(subset(x, type == "B", score$c1), list(p2 = 9, p3 = 9)) expect_identical(subset(x, type == "B", item ~ item$score$c2), list(p2 = 9, p3 = 7)) # scoping lapply(1:3, function(i) subset(x, score$c2 >= 7 + i, score$c1 + i)) # list of vectors x <- list(a = c(x = 1, y = 2), b = c(x = 3, y = 4)) expect_identical(subset(x, .["x"] >= 2, .["y"]), list(b = c(y = 4))) expect_identical(subset(x, sum(.) <= 4, max(.)), list(a = 2)) # list of lists l1 <- list(a = list(x = 1, y = 2), b = list(x = 2, y = 3)) expect_identical(subset(l1, sum(unlist(.)) <= 4, unlist(.)), list(a = c(x = 1, y = 2))) # list of objects of list mode l2 <- lapply(1:10, function(i) { x <- rnorm(100) y <- 2 * x + rnorm(100) * 0.2 lm(y ~ x) }) expect_identical(subset(l2, mean(residuals) >= 0, mean(residuals^2)), { lst <- lapply(l2, function(item) { if (mean(item$residuals) >= 0) { mean(item$residuals^2) } }) lst[vapply(lst, is.null, logical(1))] <- NULL lst }) expect_identical(subset(l2, mean(.$residuals) >= 0, mean(.$residuals^2)), { lst <- lapply(l2, function(item) { if (mean(item$residuals) >= 0) { mean(item$residuals^2) } }) lst[vapply(lst, is.null, logical(1))] <- NULL lst }) expect_identical(subset(l2, mean(resid(.)) >= 0, mean(resid(.)^2)), { lst <- lapply(l2, function(item) { if (mean(item$residuals) >= 0) { mean(item$residuals^2) } }) lst[vapply(lst, is.null, logical(1))] <- NULL lst }) # list of S4 objects # list of other objects }) rlist/tests/testthat.R0000644000176200001440000000004713650064303014535 0ustar liggesuserslibrary(testthat) test_check("rlist") rlist/NEWS0000644000176200001440000001314514114255657012124 0ustar liggesusersChanges since version 0.4 === * New features * `list.ungroup` now supports `level` arguments to `unlist` a nested list recursively. (#102) * `list.flatten` now accepts `classes` to filter list element recursively by class name. * `list.expand` implements a list version of `expand.grid` (#107) * Improvements * Support loading and parsing from xml to list. (#43) * `list.search` now uses `is.null` to clean the results. * Add `list.unzip` to `List` object. * `list.ungroup` now supports `group.names` to indicate whether to preserve group names. * Implement better error handling mechanism in `list.all`, `list.takeWhile`, `list.skipWhile`, etc. * `list.table` will directly call `table` upon input data if `...` is missing. * Bug fixes * Fix returned value of `list.unserialize`. * `list.skip` returns the original data when asked to skip 0 elements. * `list.skip` takes the first `n` elements when asked to skip a negative number of elements. * Fix bug in lambda expression handling of `list.all` (#105) Version 0.4 === * New features * Include a dataset `nyweather` scraped from [OpenWeatherMap](https://openweathermap.org/) (#2) * `list.load` now supports text-based progress bar when `progress = TRUE` which is by default enabled if over 5 files are to be loaded. (#92) * New function `list.names` gives a list or vector names by mapping. * New functions `list.first` and `list.last` find the first or last list element that meets a given condition. * New function `list.unzip` to transform a list of elements with similar structure into a list of decoupled fields. * Improvements * Add error handling in several edge cases. (#18) * `list.group` now supports grouping by multi-key which produces multi-level list. (#69) * `list.load` now supports loading from multiple filenames given in character vector. (#74) * `list.load` is now able to guess the file format even if the file type is not specified. (#76) * `list.maps` now allows the usage of `..1`, `..2`, etc. to refer to unnamed arguments. (#80) * `list.load` now supports merging and ungrouping as means to aggregating loaded results. (#82) * `list.stack` now uses `data.table::setDF` to convert `data.table` to `data.frame` if `data.table = FALSE`, which is done by reference and thus has higher performance. * Bug fixes * `list.search` now takes `n` as the number of returned vector rather than that of the elements in all returned vectors, and is now able to jump out when the result set reaches given capacity. (#47, #84) * Fix how `list.table` deals with `NULL` values. (#73) * Fix how wrapper functions deal with default arguments. (#75) * Fix the dynamic scoping issues in `list.table`. (#86) * `list.all` and `list.any` behave the same as `all` and `any` respectively when the input is empty. (#87) * One-sided formula does not result in error now. (#89) * `list.flatten` now preserves names as specified. (#90) * Fix incorrect processing for fallback in `list.findi`. (#91) * Fix the implementation in `list.group` working with multi-key. (#93) * Fix incorrect ordering if some entries are multi-valued vectors and others and single- valued. If `list.order` and `list.sort` encounter such situation, they now report error rather than silently produced unreliable results. (#94) * Fix inconsistencies in `list.all`, `list.any`, `list.first` and `list.last`. * Deprecation * `equal()` is removed and related packages are now suggested rather than imported. (#70) * `summary.list()` is deprecated. (#70) * No longer interprets `x -> f(x)` as a form a lambda expression. Use `x ~ f(x)` instead. (#54) * `desc(x)` is no longer supported in `list.sort` and `list.order`. Use `-x` or `(x)` instead. (#66) Version 0.3 === API Break: `list.search` now evaluates expression recursively in a list and supports lambda expression. Add `equal()` function for logical and fuzzy filtering and searching which supports exact equality, atomic equality, inclusion, pattern matching, string-distance tolerance. Add `List()` to provide an environment in which most list functions are defined for light-weight chaining that does not rely on external operators. Version 0.2.5 === Add `list.apply` which is a wrapper function of lapply. Add `list.search` that searches a list recursively. Add exact search functions: `equal`, `unequal`, `unidentical`, `include`, and `exclude`. Add fuzzy search functions: `like` and `unlike` based on stringdist package. Enhance `list.clean` which now supports recursive cleaning. Version 0.2.4 === Add `list.common` that returns the common cases of all list member by expression. Version 0.2.3 === Improve performance (#26, #27) Add `list.flatten` that flattens a nested list to one-level. Version 0.2.2 === Add `list.stack` that binds list members to a data.frame. Add `list.zip` that combines multiple lists element-wisely. Add `list.maps` that performs mapping over multiple lists. Performance improvements. Minor maintainence updates. `list.cases` supports list-like cases Fixed [#23](https://github.com/renkun-ken/rlist/issues/23) Fixed [#25](https://github.com/renkun-ken/rlist/issues/25) `list.select` no longer accepts explicit lambda expressions. Vignettes updated Version 0.2.1 === Add new function `list.table` Minor maintainence updates. Fixed [#6](https://github.com/renkun-ken/rlist/issues/6) Fixed [#11](https://github.com/renkun-ken/rlist/issues/11) Fixed [#20](https://github.com/renkun-ken/rlist/issues/20) Fixed [#21](https://github.com/renkun-ken/rlist/issues/21) Version 0.2 === Add `list.join`, `list.mapv`, `list.do`, `list.clean`, `list.parse` Add vignettes Version 0.1 === Implement functions rlist/R/0000755000176200001440000000000014114255253011612 5ustar liggesusersrlist/R/list.common.R0000644000176200001440000000164613650064303014204 0ustar liggesusers#' Get all common cases by expression for a list #' #' @param .data \code{list} #' @param expr An anonymous (or "lambda") expression to determine common cases. If one #' is not specified, \code{list.common} simply returns all identical sub-elements within lists. #' @export #' @examples #' x <- list(c('a','b','c'),c('a','b'),c('b','c')) #' list.common(x, .) #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.common(x,type) #' list.common(x,names(score)) #' #' foo <- list(x = LETTERS[1:3], y = LETTERS[3:5]) #' list.common(foo) list.common <- function(.data, expr) { if (!length(.data)) { return(NULL) } if(missing(expr)){ expr <- quote(.) } else { expr <- substitute(expr) } values <- list.map.internal(.data, expr, parent.frame()) return(reduce(intersect, values, values[[1L]])) } rlist/R/list.expand.R0000644000176200001440000000145413650064303014170 0ustar liggesusers#' Create a list from all combinations of factors #' #' Create a list from all combinations of the supplied #' vectors or lists, extending the functionality of #' \link{expand.grid} from data frame to list. #' #' @param ... vectors or lists #' #' @return #' A list of all combinations of the supplied vectors or #' lists. #' @export #' @examples #' list.expand(x=1:10, y=c("a","b","c")) #' list.expand(x=list(c(1,2), c(2,3)), y = c("a","b","c")) #' list.expand( #' a=list(list(x=1,y="a"), list(x=2, y="b")), #' b=list(c("x","y"), c("y","z","w"))) list.expand <- function(...) { args <- list(...) expand_args <- lapply(args, seq_along) expand_df <- do.call(expand.grid, expand_args) .mapply(function(...) { mapply(`[[`, args, list(...), USE.NAMES = TRUE, SIMPLIFY = FALSE) }, expand_df, NULL) } rlist/R/list.serialize.R0000644000176200001440000000346613650064303014705 0ustar liggesusers#' Serialize a list #' #' @param x \code{list} #' @param file The file for output #' @param type The type of serialization, including native serializer and #' json serializer, which is by default determined by file extension #' @param ... Additional parameters passed to the serializer function #' @seealso \code{\link{list.unserialize}} #' @export #' @examples #' \dontrun{ #' x <- list(a=1,b=2,c=3) #' list.serialize(x,'test.dat') #' list.serialize(x,'test.json') #' } list.serialize <- function(x, file, type = tools::file_ext(file), ...) { fun <- paste("list.serialize", tolower(type), sep = ".") if (exists(fun, mode = "function")) { fun <- get(fun, mode = "function") fun(x, file, ...) } else { conn <- file(file, open = "w") serialize(x, conn) close(conn) } invisible(x) } list.serialize.json <- function(x, file, ...) { json <- jsonlite::serializeJSON(x, ...) writeLines(json, file) } #' Unserialize a file #' #' @param file The file as input #' @param type The type of serialization, including native unserializer and #' json unserializer, which is by default determined by file extension #' @param ... Additional parameters passed to the unserializer function #' @seealso \code{\link{list.serialize}} #' @export #' @examples #' \dontrun{ #' list.unserialize('test.dat') #' list.unserialize('test.json') #' } list.unserialize <- function(file, type = tolower(tools::file_ext(file)), ...) { fun <- paste("list.unserialize", type, sep = ".") if (exists(fun, mode = "function")) { fun <- get(fun, mode = "function") fun(file, ...) } else { conn <- file(file, open = "r") res <- unserialize(conn) close(conn) res } } list.unserialize.json <- function(file, ...) { info <- file.info(file) txt <- readChar(file, info$size) jsonlite::unserializeJSON(txt, ...) } rlist/R/list.filter.R0000644000176200001440000000214113650064303014170 0ustar liggesusers#' Filter a list or vector by a series of conditions #' #' The function recursively filters the data by a given series of #' conditions. The filter can be a single condition or multiple #' conditions. \code{.data} will be filtered by the first condition; #' then the results will be filtered by the second condition, if any; #' then the results will be filtered by the third, if any, etc. The #' results only contain elements satisfying all conditions specified #' in \code{...}. #' @param .data A \code{list} or \code{vector} #' @param ... logical conditions #' @export #' @return elements in \code{.data} satisfying all conditions #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.filter(x, type=='B') #' list.filter(x, min(score$c1, score$c2) >= 8) #' list.filter(x, type=='B', score$c2 >= 8) list.filter <- function(.data, ...) { conds <- dots(...) envir <- parent.frame() reduce(function(data, cond) { data[which(list.is.internal(data, cond, envir))] }, conds, .data) } rlist/R/list.names.R0000644000176200001440000000135513650064303014014 0ustar liggesusers#' Get or set the names of a list by expression #' @param .data A \code{list} or \code{vector} #' @param expr the expression whose value will be set as the name #' for each list element. If missing then the names of the list will be #' returned. If \code{NULL} then the names of the list will be removed. #' @export #' @examples #' list.names(c(1,2,3)) #' list.names(c(a=1,b=2,c=3)) #' list.names(c(1,2,3),letters[.]) #' list.names(list(list(name='A',value=10),list(name='B',value=20)), name) list.names <- function(.data, expr) { if (missing(expr)) return(names(.data)) expr <- substitute(expr) if (is.null(expr)) return(setnames(.data, NULL)) values <- list.map.internal(.data, expr, parent.frame()) setnames(.data, values) } rlist/R/utils.R0000644000176200001440000000265313650321226013101 0ustar liggesusers#' Try to get the value of a symbol if exists or return a default value #' @details #' By default, the symbol is examined in \code{envir} without inheritance, #' that is, if the symbol does not exist in \code{envir} the default value #' \code{def} will be returned. #' @param symbol the symbol to examine #' @param def the default value if the symbol does not exist #' @param ... additional parameters passed to \code{exists} and \code{get} #' @param envir the environment to examine whether the symbol exists #' and get the symbol #' @export #' @examples #' x <- list(a=c(x=1,y=2),b=c(x=2,p=3)) #' list.map(x, tryGet(y,0)) tryGet <- function(symbol, def = NULL, ..., envir = parent.frame()) { symbol <- substitute(symbol) if (is.symbol(symbol)) symbol <- as.character(symbol) if (is.character(symbol)) { if (exists(symbol, inherits = FALSE, ..., envir = envir)) get(symbol, inherits = FALSE, ..., envir = envir) else def } else stop("symbol must be a name or character", call. = FALSE) } #' Try to evaluate an expression and return a default value if #' an error occurs or otherwise return its value. #' @param expr the expression to evaluate #' @param def the default value if an error occurs in the evaluation #' of \code{expr} #' @export #' @examples #' x <- list(a=c(x=1,y=2),b=c(x=2,p=3)) #' list.map(x, tryEval(x+y, NA)) tryEval <- function(expr, def = NULL) { x <- try(expr, silent = TRUE) if (is.error(x)) def else x } rlist/R/list.search.R0000644000176200001440000000674013650064303014161 0ustar liggesusers#' Search a list recusively by an expression #' #' @param .data A \code{list} or \code{vector} #' @param expr a lambda expression #' @param classes a character vector of class names that restrict the search. #' By default, the range is unrestricted (\code{ANY}). #' @param n the maximal number of vectors to return #' @param unlist \code{logical} Should the result be unlisted? #' @details #' \code{list.search} evaluates an expression (\code{expr}) recursively #' along a list (\code{.data}). #' #' If the expression results in a single-valued logical vector and its #' value is \code{TRUE}, the whole vector will be collected If it results #' in multi-valued or non-logical vector, the non-\code{NA} values #' resulted from the expression will be collected. #' #' To search whole vectors that meet certain condition, specify the #' expression that returns a single logical value. #' #' To search the specific values within the vectors, use subsetting in the #' expression, that is, \code{.[cond]} or lambda expression like #' \code{x -> x[cond]} where \code{cond} is a logical vector used to #' select the elements in the vector. #' @name list.search #' @export #' @examples #' # Exact search #' #' x <- list(p1 = list(type='A',score=c(c1=9)), #' p2 = list(type=c('A','B'),score=c(c1=8,c2=9)), #' p3 = list(type=c('B','C'),score=c(c1=9,c2=7)), #' p4 = list(type=c('B','C'),score=c(c1=8,c2=NA))) #' #' ## Search exact values #' list.search(x, identical(., 'A')) #' list.search(x, identical(., c('A','B'))) #' list.search(x, identical(., c(9,7))) #' list.search(x, identical(., c(c1=9,c2=7))) #' #' ## Search all equal values #' list.search(x, all(. == 9)) #' list.search(x, all(. == c(8,9))) #' list.search(x, all(. == c(8,9), na.rm = TRUE)) #' #' ## Search any equal values #' list.search(x, any(. == 9)) #' list.search(x, any(. == c(8,9))) #' #' # Fuzzy search #' #' data <- list( #' p1 = list(name='Ken',age=24), #' p2 = list(name='Kent',age=26), #' p3 = list(name='Sam',age=24), #' p4 = list(name='Keynes',age=30), #' p5 = list(name='Kwen',age=31) #' ) #' #' list.search(data, grepl('^K\\w+n$', .), 'character') #' #' \dontrun{ #' library(stringdist) #' list.search(data, stringdist(., 'Ken') <= 1, 'character') #' list.search(data, stringdist(., 'Man') <= 2, 'character') #' list.search(data, stringdist(., 'Man') > 2, 'character') #' } #' #' data <- list( #' p1 = list(name=c('Ken', 'Ren'),age=24), #' p2 = list(name=c('Kent', 'Potter'),age=26), #' p3 = list(name=c('Sam', 'Lee'),age=24), #' p4 = list(name=c('Keynes', 'Bond'),age=30), #' p5 = list(name=c('Kwen', 'Hu'),age=31)) #' #' list.search(data, .[grepl('e', .)], 'character') #' #' \dontrun{ #' list.search(data, all(stringdist(., 'Ken') <= 1), 'character') #' list.search(data, any(stringdist(., 'Ken') > 1), 'character') #' } list.search <- function(.data, expr, classes = "ANY", n, unlist = FALSE) { vec <- rapply(.data, function(x) TRUE, classes = classes) if (missing(n)) n <- sum(vec) l <- lambda(substitute(expr)) args <- args_env(i = 0L, n = 0L, N = n, indices = integer(n), result = vector("list", n)) fun <- list.search.fun environment(fun) <- parent.frame() formals(fun) <- setnames(formals(fun), c(".data", ".expr", ".args", ".n", l$symbols)) tryWithCondition(rapply(.data, fun, classes = classes, .expr = l$expr, .args = args), rlist.finished = NULL) result <- list.clean(args$result, recursive = FALSE) names(result) <- names(vec)[args$indices] if (unlist) result <- c(result, recursive = TRUE) result } rlist/R/functions.R0000644000176200001440000000714014114255253013747 0ustar liggesusers# compatibility for data.table functions .datatable.aware <- TRUE #' Substitute ... #' @param ... parameters to substitute dots <- function(...) { eval(substitute(alist(...))) } #' Evaluate a function with a modified default values #' @param fun either a function or a non-empty character string naming the function to be called #' @param args a list of values to modify the default arguments of the function #' @param dots the user-specific input (usually from ...) #' @param keep.null \code{TRUE} to keep \code{NULL} values after argument modifications #' @param envir the environment to evaluate the function call #' @importFrom utils modifyList callwith <- function(fun, args, dots = list(), keep.null = FALSE, envir = parent.frame()) { do.call(fun, modifyList(args, dots, keep.null = keep.null), envir = envir) } setnames <- `names<-` setclass <- `class<-` setmembers <- `[<-` is.formula <- function(expr) { inherits(expr, "formula") || (is.call(expr) && expr[[1L]] == "~") } is.error <- function(x) { inherits(x, "try-error") } #' Test if a vector contains certain values #' @param table the values to be matched against #' @param x the values to be matched contains <- function(table, x) { match(x, table, nomatch = 0L) > 0L } #' Get the names of an object #' @details This function is used in vectorization when the names of an object #' is to be supplied. \code{NULL} value will break the vectorization while #' setting \code{def = character(1L)} makes the names vectorizable. #' @param x the object to extract names #' @param def the value to return if the object has \code{NULL} names. #' For vectorization purpose, set this to \code{character(1L)}. getnames <- function(x, def = NULL) if (is.null(names(x))) def else names(x) #' Check if an object is empty (has length 0) #' @details A \code{NULL} value, zero-length vector or list have length zero, #' which is called empty. #' @param x the object is.empty <- function(x) length(x) == 0L #' Make names for unnamed symbol arguments #' @details The elements of an unevaluated list of arguments may or may not #' have names as given by user. For example, \code{list.select} requires user #' to specify the fields to select. These fields are unevaluated arguments, #' some of which are symbols and others are calls. For the symbols, it is natural #' to make the resulted lists to have the same name for the particular arguments. #' @param args the unevaluated argument list #' @param data the list to be named (\code{args} by default) set_argnames <- function(args, data = args) { argnames <- getnames(args, character(length(args))) indices <- !nzchar(argnames) & vapply(args, is.name, logical(1L)) argnames[indices] <- as.character(args[indices]) setnames(data, argnames) } try_list <- function(exprs, finally, envir = NULL, enclos = parent.frame()) { for (expr in exprs) { result <- try(eval(expr, envir, enclos), silent = TRUE) if (!inherits(result, "try-error")) return(result) } if (missing(finally)) stop("No valid results produced", call. = FALSE) eval(substitute(finally), envir, enclos) } #' Convert an object to evaluating environment for list elements Users should not #' directly use this function #' @param x the object .evalwith <- function(x) { if (is.null(names(x))) NULL else if (is.list(x)) x else if (is.vector(x)) setclass(x, "list") else NULL } #' create an environment for args #' @param ... objects #' @param parent parent environment args_env <- function(..., parent = parent.frame()) { list2env(list(...), parent = parent) } #' create a list for args #' @param ... objects args_list <- function(...) { list(...) } rlist/R/list.remove.R0000644000176200001440000000244313650064303014205 0ustar liggesusers#' Remove members from a list by index or name #' #' @param .data A \code{list} or \code{vector} #' @param range A numeric vector of indices or #' a character vector of names to remove from \code{.data} #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.remove(x, 'p1') #' list.remove(x, c(1,2)) list.remove <- function(.data, range = integer()) { if (is.logical(range)) { .data[!range] } else if (is.numeric(range)) { .data[-range] } else if (is.character(range)) { names <- names(.data) m <- vapply(range, "==", logical(length(.data)), names) selector <- apply(m, 1L, any) .data[!selector] } } #' Exclude members of a list that meet given condition. #' #' @param .data A \code{list} or \code{vector} #' @param cond A logical lambda expression to exclude items #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.exclude(x, type=='B') #' list.exclude(x, min(score$c1,score$c2) >= 8) list.exclude <- function(.data, cond) { .data[!list.is.internal(.data, substitute(cond), parent.frame())] } rlist/R/list.all.R0000644000176200001440000000411713650064303013460 0ustar liggesusers#' Examine if a condition is true for all elements of a list #' #' @param .data A \code{list} or \code{vector} #' @param cond A logical lambda expression #' @param na.rm logical. If true \code{NA} values are ignored in #' the evaluation. #' @seealso \code{\link{list.any}} #' @return \code{TRUE} if \code{cond} is evaluated to be \code{TRUE} #' for all elements in \code{.data}. #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.all(x, type=='B') #' list.all(x, mean(unlist(score))>=6) #' list.all(x, score$c2 > 8 || score$c3 > 5, na.rm = TRUE) #' list.all(x, score$c2 > 8 || score$c3 > 5, na.rm = FALSE) list.all <- function(.data, cond, na.rm = FALSE) { if (missing(.data)) return(all(na.rm = na.rm)) if (is.empty(.data) || missing(cond)) return(all(.data, na.rm = na.rm)) l <- lambda(substitute(cond)) l$expr <- as.call(list(quote(`!`), l$expr)) res <- list.first.internal(.data, l, parent.frame(), na.rm = na.rm) !res$state } #' Examine if a condition is true for at least one list element #' #' @param .data A \code{list} or \code{vector} #' @param cond A logical lambda expression #' @param na.rm logical. If true \code{NA} values are ignored in #' the evaluation. #' @seealso \code{\link{list.all}} #' @return \code{TRUE} if \code{cond} is evaluated to be \code{TRUE} #' for any element in \code{.data}. #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.any(x,type=='B') #' list.any(x,mean(unlist(score))>=6) #' list.any(x, score$c2 > 8 || score$c3 > 5, na.rm = TRUE) #' list.any(x, score$c2 > 8 || score$c3 > 5, na.rm = FALSE) list.any <- function(.data, cond, na.rm = FALSE) { if (missing(.data)) return(any(na.rm = na.rm)) if (is.empty(.data) || missing(cond)) return(any(.data, na.rm = na.rm)) res <- list.first.internal(.data, substitute(cond), parent.frame(), na.rm = na.rm) res$state } rlist/R/list.match.R0000644000176200001440000000110313650064303013774 0ustar liggesusers#' Select members of a list that match given regex pattern #' #' @param .data A \code{list} or \code{vector} #' @param pattern \code{character}. The regex pattern to match the name of the members #' @param ... Additional parameters to pass to \code{grep} #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.match(x,'p[12]') #' list.match(x,'3') list.match <- function(.data, pattern, ...) { .data[grep(pattern, names(.data), ...)] } rlist/R/list.load.R0000644000176200001440000000667213650064303013637 0ustar liggesusers#' Load a list from file #' #' @param file a \code{character} vector. The file as input. #' @param type The type of input which, by default, is determined #' by file extension. Currently supports RData, RDS, JSON, YAML. #' @param ... Additional parameters passed to the loader function #' @param guess a \code{character} vector to guess iteratively if #' \code{type} of \code{file} is unrecognized, \code{NA} or empty #' string. #' @param action The post-processing action if multiple files are #' supplied. This parameter will be ignored if only a single file #' is supplied. #' #' \code{'none'} (default) to leave the resulted list as #' a list of elements corresponding to elements in \code{file} #' vector. #' #' \code{'merge'} to merge the list elements iteratively, #' the later lists always modify the former ones through #' \code{modifyList}. #' #' \code{'ungroup'} to ungroup the list elements, especially when #' each file is a page of elements with identical structure. #' @param progress \code{TRUE} to show a text progress bar in console #' while loading files. By default, if \code{file} contains 5 elements, #' then the progress bar will automatically be triggered to indicate #' loading progress. #' @importFrom utils txtProgressBar #' @export #' @examples #' \dontrun{ #' list.load('list.rds') #' list.load('list.rdata') #' list.load('list.yaml') #' list.load('list.json') #' } list.load <- function(file, type = tools::file_ext(file), ..., guess = c("json", "yaml", "rds", "rdata", "xml"), action = c("none", "merge", "ungroup"), progress = length(file) >= 5L) { if (length(file) == 0L) return(list()) nztype <- !is.na(type) & nzchar(type) fun <- paste("list.loadfile", tolower(type), sep = ".") fun[!nztype] <- NA_character_ guess <- tolower(guess) pb <- if (progress) txtProgressBar(min = 0L, max = length(file), style = 3L) else NULL res <- if (length(file) == 1L) list.loadfile(file, fun, guess, ..., pb = pb, index = 1L) else { items <- map(list.loadfile, list(file, fun, index = seq_along(file)), list(guess = guess, ..., pb = pb)) switch(match.arg(action), merge = do.call("list.merge", items), ungroup = list.ungroup(items), items) } if (!is.null(pb)) close(pb) res } list.loadfile <- function(file, fun, guess, ..., pb = NULL, index = NULL) { res <- NULL if (is.na(fun)) { if (!missing(guess) && length(guess) > 0L) { exprs <- lapply(paste("list.loadfile", guess, sep = "."), function(f) call(f, file)) res <- try_list(exprs, stop("Unrecognized type of file: ", file, call. = FALSE)) if (!is.null(pb)) pb$up(index) } else stop("Unrecognized type of file: ", file, call. = FALSE) } else if (exists(fun, mode = "function")) { fun <- get(fun, mode = "function") res <- fun(file, ...) if (!is.null(pb)) pb$up(index) } else { stop("Unrecognized type of file: ", file, call. = FALSE) } res } list.loadfile.json <- function(file, ...) { callwith(jsonlite::fromJSON, list(file, simplifyDataFrame = FALSE), list(...)) } list.loadfile.yaml <- function(file, ...) { yaml::yaml.load_file(file, ...) } list.loadfile.yml <- list.loadfile.yaml list.loadfile.xml <- function(file, ...) { xmlData <- XML::xmlParse(file, ...) XML::xmlToList(xmlData) } list.loadfile.rdata <- function(file, name = "x") { env <- new.env(parent = parent.frame(), size = 1L) load(file, env) env[[name]] } list.loadfile.rds <- function(file, ...) readRDS(file, ...) rlist/R/list.is.R0000644000176200001440000000134413650064303013322 0ustar liggesusers#' Return a logical vector that indicates if each member of a list #' satisfies a given condition #' #' @param .data \code{list} #' @param cond A logical lambda expression #' @param use.names \code{logical} Should the names of \code{.data} be kept? #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.is(x,type=='B') #' list.is(x,min(score$c1,score$c2) >= 8) list.is <- function(.data, cond, use.names = TRUE) { items <- list.is.internal(.data, substitute(cond), parent.frame()) if (use.names) setnames(items, names(.data)) else items } #' @export #' @rdname list.is list.if <- list.is rlist/R/list.map.R0000644000176200001440000000576313650064303013475 0ustar liggesusers#' Map each element in a list or vector by an expression. #' #' @param .data a \code{list} or \code{vector} #' @param expr A lambda expression #' @return A \code{list} in which each element is mapped by \code{expr} in \code{.data} #' @export #' @seealso \code{\link{list.mapv}} #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.map(x, type) #' list.map(x, min(score$c1,score$c2)) list.map <- function(.data, expr) { list.map.internal(.data, substitute(expr), parent.frame()) } #' Map each member of a list by an expression to a vector. #' #' @param .data a \code{list} or \code{vector} #' @param expr a lambda expression #' @param as the mode to corece. Missing to \code{unlist} #' the mapped results. #' @param use.names Should the names of the results be preserved? #' @return A \code{vector} in which each element is mapped by \code{expr} in \code{.data} #' @export #' @seealso \code{\link{list.map}} #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.mapv(x, type) #' list.mapv(x, min(score$c1,score$c2)) list.mapv <- function(.data, expr, as, use.names = TRUE) { res <- list.map.internal(.data, substitute(expr), parent.frame()) if (missing(as)) unlist(res, use.names = use.names) else { res <- as.vector(res, as) if (use.names && !is.null(nm <- names(.data))) names(res) <- nm res } } #' Map multiple lists with an expression #' #' @param expr An implicit lambda expression where only \code{.i} and #' \code{.name} are defined. #' @param ... Named arguments of lists with equal length. The names of the #' lists are available as symbols that represent the element for each list. #' @name list.maps #' @export #' @examples #' \dontrun{ #' l1 <- list(p1=list(x=1,y=2), p2=list(x=3,y=4), p3=list(x=1,y=3)) #' l2 <- list(2,3,5) #' list.maps(a$x*b+a$y,a=l1,b=l2) #' list.maps(..1$x*..2+..1$y,l1,l2) #' } list.maps <- function(expr, ...) { expr <- substitute(expr) envir <- parent.frame() lists <- list(...) if (is.empty(lists)) return(list()) list1 <- lists[[1L]] xnames <- getnames(list1, character(1L)) fun <- with(envir, function(..., .expr) eval(.expr, list(...))) args <- c(lists, list(.i = seq_along(list1), .name = xnames, .expr = list(expr))) map(fun, args) } #' Iterate a list by evaluating an expression on #' each list element #' #' @param .data \code{list} #' @param expr A lambda expression #' @name list.iter #' @export #' @return \code{invisible(.data)} #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.iter(x,cat(paste(type,'\n'))) #' list.iter(x,cat(str(.))) list.iter <- function(.data, expr) { list.map.internal(.data, substitute(expr), parent.frame()) invisible(.data) } rlist/R/list.stack.R0000644000176200001440000000155313650064303014016 0ustar liggesusers#' Stack all list elements to tabular data #' #' @param .data \code{list} of \code{vector}s, \code{list}s, #' \code{data.frame}s or \code{data.table}s. #' @param ... additional parameters passed to \code{data.table::rbindlist}. #' @param data.table \code{TRUE} to keep the result as \code{data.table} #' @export #' @importFrom data.table rbindlist #' @examples #' \dontrun{ #' x <- lapply(1:3, function(i) { list(a=i,b=i^2) }) #' list.stack(x) #' #' x <- lapply(1:3, function(i) { list(a=i,b=i^2,c=letters[i])}) #' list.stack(x) #' #' x <- lapply(1:3, function(i) { data.frame(a=i,b=i^2,c=letters[i]) }) #' list.stack(x) #' #' x <- lapply(1:3, function(i) { data.frame(a=c(i,i+1), b=c(i^2,i^2+1))}) #' list.stack(x) #' } list.stack <- function(.data, ..., data.table = FALSE) { dt <- data.table::rbindlist(.data, ...) if (!data.table) data.table::setDF(dt) dt } rlist/R/list.take.R0000644000176200001440000000303213650064303013627 0ustar liggesusers#' Take a number of elements #' #' Take the first \code{n} elements out from a list or #' vector. #' #' @param .data \code{list} or \code{vector} #' @param n \code{integer}. The number of elements to take #' @param force \code{TRUE} to disable the length check #' @export #' @seealso \code{\link{list.takeWhile}}, \code{\link{list.skip}}, #' \code{\link{list.skipWhile}} #' @examples #' x <- list(a=1,b=2,c=3) #' list.take(x,1) #' list.take(x,10) list.take <- function(.data, n, force = FALSE) { if(!is.numeric(n)) stop("n must be numeric or integer", call. = FALSE) .data[0L:if(force) n else min(length(.data), n)] } #' Keep taking elements while a condition holds #' #' Keep taking elements out from a list or vector while #' a condition holds for the element. If the condition is #' violated for an element, the element will not be taken and #' all taken elements will be returned. #' #' @param .data \code{list} or \code{vector} #' @param cond A logical lambda expression #' @export #' @seealso \code{\link{list.take}}, \code{\link{list.skip}}, #' \code{\link{list.skipWhile}} #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.takeWhile(x, type=='B') #' list.takeWhile(x, min(score$c1,score$c2) >= 8) list.takeWhile <- function(.data, cond) { args <- args_env(i = 0L) tryWithCondition(list.map.internal(.data, substitute(cond), parent.frame(), list.while.fun, args), rlist.finished = NULL) .data[0L:args$i] } rlist/R/list.clean.R0000644000176200001440000000340213650064303013766 0ustar liggesusers#' Clean a list by a function #' #' This function removes all elements evaluated to be #' \code{TRUE} by an indicator function. The removal can be recursive #' so that the resulted list surely does not include such elements in #' any level. #' #' @details #' Raw data is usually not completely ready for analysis, and needs to #' be cleaned up to certain standards. For example, some data operations #' require that the input does not include \code{NULL} values in any #' level, therefore \code{fun = "is.null"} and \code{recursive = TRUE} #' can be useful to clean out all \code{NULL} values in a list at any #' level. #' #' Sometimes, not only \code{NULL} values are undesired, #' empty vectors or lists are also unwanted. In this case, #' \code{fun = function(x) length(x) == 0L} can be useful to remove #' all empty elements of zero length. This works because #' \code{length(NULL) == 0L}, \code{length(list()) == 0L} and #' \code{length(numeric()) == 0L} are all \code{TRUE}. #' #' @param .data A \code{list} or \code{vector} to operate over. #' #' @param fun A \code{character} or a \code{function} that returns #' \code{TRUE} or \code{FALSE} to indicate if an element of #' \code{.data} should be removed. #' #' @param recursive \code{logical}. Should the list be #' cleaned recursively? Set to FALSE by default. #' @export #' @examples #' x <- list(a=NULL,b=list(x=NULL,y=character()),d=1,e=2) #' list.clean(x) #' list.clean(x, recursive = TRUE) #' list.clean(x, function(x) length(x) == 0L, TRUE) list.clean <- function(.data, fun = is.null, recursive = FALSE) { if (recursive) { .data <- lapply(.data, function(.item) { if (is.list(.item)) list.clean(.item, fun, recursive = TRUE) else .item }) } setmembers(.data, vapply(.data, fun, logical(1L)), NULL) } rlist/R/list.parse.R0000644000176200001440000000435513650064303014026 0ustar liggesusers#' Convert an object to list with identical structure #' #' This function converts an object representing data to #' list that represents the same data. For example, a #' \code{data.frame} stored tabular data column-wisely, #' that is, each column represents a vector of a certain #' type. \code{list.parse} converts a \code{data.frame} to #' a list which represents the data row-wisely so that it #' can be more convinient to perform other non-tabular data #' manipulation methods. #' @param x \code{An object} #' @param ... Additional parameters passed to converter function #' @return \code{list} object representing the data in \code{x} #' @export #' @examples #' x <- data.frame(a=1:3,type=c('A','C','B')) #' list.parse(x) #' #' x <- matrix(rnorm(1000),ncol=5) #' rownames(x) <- paste0('item',1:nrow(x)) #' colnames(x) <- c('a','b','c','d','e') #' list.parse(x) #' #' z <- ' #' a: #' type: x #' class: A #' registered: yes #' ' #' list.parse(z, type='yaml') list.parse <- function(x, ...) UseMethod("list.parse") #' @export #' @rdname list.parse list.parse.default <- function(x, ...) { as.list(x, ...) } #' @export #' @rdname list.parse list.parse.matrix <- function(x, ...) { apply(x, 1L, as.vector, mode = "list") } #' @export #' @rdname list.parse list.parse.data.frame <- function(x, ...) { cols <- colnames(x) items <- map(function(...) setnames(list(...), cols), x) setnames(items, rownames(x)) } #' @export #' @rdname list.parse #' @param type The type of data to parse. Currently json and yaml are supported. list.parse.character <- function(x, type, ...) { if (length(x) == 0L) return(list()) else if (length(x) == 1L) { if (missing(type) || length(type) == 0L || is.na(type)) { list.parse.default(x, ...) } else if (tolower(type) == "yaml") { yaml::yaml.load(x, ...) } else if (tolower(type) == "json") { callwith(jsonlite::fromJSON, list(x, simplifyVector = FALSE, simplifyDataFrame = FALSE, simplifyMatrix = FALSE), list(...)) } else if (tolower(type) == "xml") { XML::xmlToList(XML::xmlParseString(x, ...)) } else { stop("Unsupported type of data", call. = FALSE) } } else if (length(x) > 1L) { map(list.parse.character, list(x, type), list(...), use.names = FALSE) } } rlist/R/data.R0000644000176200001440000000056514114255721012654 0ustar liggesusers#' New York hourly weather data #' #' A non-tabular data of the hourly weather conditions of the New York City #' from 2013-01-01 to 2013-03-01. #' #' Fetch date: 2014-11-23. #' #' Processed by rlist. #' #' To retrieve the data, please visit \url{https://openweathermap.org/api} for #' API usage. #' @format #' See \url{https://openweathermap.org/weather-data} "nyweather" rlist/R/list.subset.R0000644000176200001440000000057513650064303014221 0ustar liggesusers#' Subset a list #' #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.subset(x, c('p1','p2')) #' list.subset(x, grepl('^p', names(x))) #' \dontrun{ #' list.subset(x, stringdist::stringdist(names(x), 'x1') <= 1) #' } list.subset <- `[` rlist/R/list.zip.R0000644000176200001440000000742713650064303013521 0ustar liggesusers#' Combine multiple lists element-wisely. #' #' @param ... \code{list}s #' @param use.argnames \code{logical}. Should the names of the #' arguments be used as the names of list items? #' @param use.names \code{logical}. Should the names of the first #' argument be used as the zipped list? #' @export #' @seealso \code{\link{list.unzip}} #' @examples #' x <- list(1,2,3) #' y <- list('x','y','z') #' list.zip(num=x,sym=y) list.zip <- function(..., use.argnames = TRUE, use.names = TRUE) { args <- list(...) if (use.argnames) args <- set_argnames(dots(...), args) results <- map(args_list, args) if (!use.names) names(results) <- NULL results } #' Transform a list of elements with similar structure into a list of decoupled fields #' #' @param .data A \code{list} of elements containing common fields #' @param .fields \code{'intersect'} to select only common fields for #' all \code{.data}'s elements. \code{'union'} to select any field that #' is defined in any elements in \code{.data}. #' @param ... The custom aggregate functions. Can be a named list of functions or #' character vectors. If a function is specified as a list of functions, then the #' functions will be evaluated recursively on the result of the field. Use \code{identity} to #' avoid aggregating results. Use \code{NULL} to remove certain field. #' @param .aggregate The default aggregate function, by default, \code{simplify2array}. #' Can be a function, character vector or a list of functions. Use \code{identity} to avoid #' aggregating results. #' @param .missing When \code{.fields} is \code{'union'} and some elements do not contain #' certain fields, then \code{NULL} will be replaced by the value of \code{.missing}, #' by default, \code{NA}. This often makes the result more friendly. #' @importFrom stats na.omit #' @export #' @seealso \code{\link{list.zip}} #' @examples #' list.unzip(list(p1 = list(a = 1, b = 2), p2 = list(a = 2, b = 3))) #' list.unzip(list(p1 = list(a = 1, b = 2), p2 = list(a = 2, b = 3, c = 4))) #' list.unzip(list(p1 = list(a = 1, b = 2), p2 = list(a = 2, b = 3, c = 4)), 'union') #' list.unzip(list(p1 = list(a = 1, b = 2), p2 = list(a = 2, b = 3, c = 4)), 'union', a = 'identity') #' list.unzip(list(p1 = list(a = 1, b = 2), p2 = list(a = 2, b = 3, c = 4)), 'intersect', a = NULL) #' #' x <- #' list(april = list(n_days = 30, #' holidays = list(list('2015-04-01', 'april fools'), #' list('2015-04-05', 'easter')), #' month_info = c(number = '4', season = 'spring')), #' july = list(n_days = 31, #' holidays = list(list('2014-07-04', 'july 4th')), #' month_info = c(number = '7', season = 'summer'))) #' list.unzip(x, holidays = c('list.ungroup', 'unname', 'list.stack', #' function(df) setNames(df, c("date", "name")))) list.unzip <- function(.data, .fields = c("intersect", "union"), ..., .aggregate = "simplify2array", .missing = NA) { data_names <- lapply(.data, names) aggregator <- lapply(.aggregate, match.fun) args <- list(...) if (length(args) >= 1L && (is.null(names(args)) || !all(nzchar(names(args))))) stop("Custom aggregate function must have a name", call. = FALSE) args <- lapply(args, function(f) { if (is.null(f)) NULL else if (is.vector(f)) lapply(f, match.fun) else match.fun(f) }) fields <- Reduce(match.fun(match.arg(.fields)), data_names) names(fields) <- fields fields[names(args)[vapply(args, is.null, logical(1L))]] <- NA fields <- na.omit(fields) lapply(fields, function(field) { items <- lapply(.data, "[[", field) if (!is.null(.missing)) { missings <- vapply(items, is.null, logical(1L)) items[missings] <- .missing } agg_fun <- if (!is.null(args[[field]])) args[[field]] else aggregator if (is.list(agg_fun)) { reduce(function(res, f) f(res), agg_fun, items) } else agg_fun(items) }) } rlist/R/list.which.R0000644000176200001440000000107013650064303014005 0ustar liggesusers#' Give the indices of list elements satisfying #' a given condition #' #' @param .data A \code{list} or \code{vector} #' @param cond A logical lambda expression #' @return an \code{integer} vector #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.which(x, type == 'B') #' list.which(x, min(score$c1,score$c2) >= 8) list.which <- function(.data, cond) { which(list.is.internal(.data, substitute(cond), parent.frame())) } rlist/R/list.sample.R0000644000176200001440000000157613650064303014177 0ustar liggesusers#' Sample a list or vector #' #' @param .data A \code{list} or \code{vector} #' @param size \code{integer}. The size of the sample #' @param replace \code{logical}. Should sampling be with replacement? #' @param weight A lambda expression to determine the weight of #' each list member, which only takes effect if \code{prob} #' is \code{NULL}. #' @param prob A \code{vector} of probability weights for #' obtaining the elements of the list being sampled. #' @export #' @examples #' x <- list(a = 1, b = c(1,2,3), c = c(2,3,4)) #' list.sample(x, 2, weight = sum(.)) list.sample <- function(.data, size, replace = FALSE, weight = 1, prob = NULL) { if (is.null(prob)) { ws <- c(list.map.internal(.data, substitute(weight), parent.frame()), recursive = TRUE) if (any(ws < 0)) stop("Negative weight is not allowed") prob <- ws/sum(ws) } sample(.data, size, replace, prob) } rlist/R/list.count.R0000644000176200001440000000147613650064303014045 0ustar liggesusers#' Count the number of elements that satisfy given condition #' #' @param .data A \code{list} or \code{vector} #' @param cond A logical lambda expression for each element of \code{.data} to evaluate. If #' \code{cond} is missing then the total number of elements in \code{.data} will be returned. #' @return An integer that indicates the number of elements with which \code{cond} is evaluated #' to be \code{TRUE}. #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.count(x, type=='B') #' list.count(x, min(unlist(score)) >= 9) list.count <- function(.data, cond) { if (missing(cond)) return(length(.data)) length(which(list.is.internal(.data, substitute(cond), parent.frame()))) } rlist/R/list.skip.R0000644000176200001440000000300713650064303013653 0ustar liggesusers#' Skip a number of elements #' #' Skip the first \code{n} elements of a list or vector and #' return the remaining elements if any. #' #' @param .data A \code{list} or \code{vector} #' @param n \code{integer}. The number of elements to skip #' @export #' @seealso \code{\link{list.skipWhile}}, \code{\link{list.take}}, #' \code{\link{list.takeWhile}} #' @examples #' x <- list(a=1,b=2,c=3) #' list.skip(x, 1) #' list.skip(x, 2) list.skip <- function(.data, n) { if(!is.numeric(n)) stop("n must be numeric or integer", call. = FALSE) if(n > 0L) .data[-(1L:n)] else if(n < 0L) .data[1L:(-n)] else .data } #' Keep skipping elements while a condition holds #' #' Keep skipping elements in a list or vector while a #' condition holds for the element. As long as the condition #' is violated, the element will be kept and all remaining #' elements are returned. #' #' @param .data A \code{list} or \code{vector} #' @param cond A logical lambda expression #' @export #' @seealso \code{\link{list.skip}}, \code{\link{list.take}}, #' \code{\link{list.takeWhile}} #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.skipWhile(x, type=='A') #' list.skipWhile(x, min(score$c1,score$c2) >= 8) list.skipWhile <- function(.data, cond) { args <- args_env(i = 0L) tryWithCondition(list.map.internal(.data, substitute(cond), parent.frame(), list.while.fun, args), rlist.finished = NULL) .data[-(0L:args$i)] } rlist/R/rlist.R0000644000176200001440000000126314114255757013105 0ustar liggesusers#' The rlist package #' @name rlist-package #' @docType package #' @description #' rlist is a set of tools for working with list objects. Its goal #' is to make it easier to work with lists by providing a wide range #' of functions that operate on non-tabular data stored in them. #' #' The package provides a set of functions for data manipulation with #' list objects, including mapping, filtering, grouping, sorting, #' updating, searching, and other useful functions. Most functions #' are designed to be pipeline friendly so that data processing with #' lists can be chained. #' #' rlist Tutorial (\url{https://renkun-ken.github.io/rlist-tutorial/}) is a complete guide to rlist. NULL rlist/R/list.join.R0000644000176200001440000000361013650064303013644 0ustar liggesusers#' Join two lists by single or multiple keys #' @param x The first list #' @param y The second list #' @param xkey A lambda expression that determines the key for list \code{x} #' @param ykey A lambda expression that determines the key for list \code{y}, #' same to \code{xkey} if missing #' @param ... The additional parameters passed to \code{merge.data.frame} #' @param keep.order Should the order of \code{x} be kept? #' @export #' @importFrom utils modifyList #' @examples #' l1 <- list(p1=list(name='Ken',age=20), #' p2=list(name='James',age=21), #' p3=list(name='Jenny',age=20)) #' l2 <- list(p1=list(name='Jenny',age=20,type='A'), #' p2=list(name='Ken',age=20,type='B'), #' p3=list(name='James',age=22,type='A')) #' list.join(l1, l2, name) #' list.join(l1, l2, .[c('name','age')]) list.join <- function(x, y, xkey, ykey, ..., keep.order = TRUE) { if (missing(xkey) && missing(ykey)) stop("At least one key should be specified") sxkey <- substitute(xkey) sykey <- substitute(ykey) dfsxkey <- substitute(data.frame(xkey)) if (missing(sykey)) { sykey <- sxkey dfsykey <- substitute(data.frame(xkey)) } else { dfsykey <- substitute(data.frame(ykey)) } xkeys.list <- list.map.internal(x, dfsxkey, parent.frame()) ykeys.list <- list.map.internal(y, dfsykey, parent.frame()) xkeys.df <- list.rbind(xkeys.list) ykeys.df <- list.rbind(ykeys.list) if (is.name(sxkey)) colnames(xkeys.df) <- as.character(sxkey) if (is.name(sykey)) colnames(ykeys.df) <- as.character(sykey) if (!identical(colnames(xkeys.df), colnames(ykeys.df))) { stop("Inconsistent keys") } xkeys <- cbind(.xi = seq_along(xkeys.list), xkeys.df) ykeys <- cbind(.yi = seq_along(ykeys.list), ykeys.df) df <- merge.data.frame(xkeys, ykeys, by = colnames(xkeys)[-1L], ...) if (keep.order) df <- df[order(df$.xi), ] map(modifyList, list(x[df$.xi], y[df$.yi])) } rlist/R/list.order.R0000644000176200001440000000324313650064303014022 0ustar liggesusers#' Give the order of each list element by expression #' #' @param .data A \code{list} or \code{vector} #' @param ... A group of lambda expressions #' @param keep.names Whether to keep the names of \code{x} in the result #' @param na.last The way to deal with \code{NA}s. #' @export #' @return an \code{integer} vector. #' @seealso \code{\link{list.sort}} #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.order(x, type, (score$c2)) # order by type (ascending) and score$c2 (descending) #' list.order(x, min(score$c1,score$c2)) #' list.order(x, min(score$c1,score$c2), keep.names=TRUE) list.order <- function(.data, ..., keep.names = FALSE, na.last = TRUE) { result <- list.order.internal(.data, dots(...), parent.frame(), na.last = na.last) if (keep.names) setnames(result, names(.data)) else result } #' Sort a list by given expressions #' #' @param .data a \code{list} or \code{vector} #' @param ... A group of lambda expressions. For each expression, the data #' is sorted ascending by default unless the expression is enclosed by (). #' @param na.last The way to deal with \code{NA}s. #' @seealso \code{\link{list.order}} #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.sort(x, type, (score$c2)) # sort by score$c2 in descending order #' list.sort(x, min(score$c1,score$c2)) list.sort <- function(.data, ..., na.last = NA) { .data[list.order.internal(.data, dots(...), parent.frame(), na.last = na.last)] } rlist/R/list.save.R0000644000176200001440000000263313650064303013647 0ustar liggesusers#' Save a list to a file #' #' @param x The list to save #' @param file The file for output #' @param type The type of output which, by default, is determined #' by file extension. Currently supports RData, RDS, JSON, YAML. #' @param ... Additional parameters passed to the output function #' @export #' @return \code{x} will be returned. #' @examples #' \dontrun{ #' x <- lapply(1:5,function(i) data.frame(a=i,b=i^2)) #' list.save(x, 'list.rds') #' list.save(x, 'list.rdata') #' list.save(x, 'list.yaml') #' list.save(x, 'list.json') #' } list.save <- function(x, file, type = tools::file_ext(file), ...) { fun <- paste("list.savefile", tolower(type), sep = ".") if (exists(fun, mode = "function")) { fun <- get(fun, mode = "function") fun(x, file, ...) } else { stop("Unrecognized type of file: ", file, call. = FALSE) } invisible(x) } list.savefile.json <- function(x, file, ...) { json <- jsonlite::toJSON(x, ...) writeLines(json, file) } list.savefile.yaml <- function(x, file, ...) { yaml <- yaml::as.yaml(x, ...) writeLines(yaml, file) } list.savefile.yml <- list.savefile.yaml list.savefile.rdata <- function(x, file, name = "x", ...) { if (!is.list(x)) stop("x is not a list") env <- new.env(parent = parent.frame(), size = 1L) assign(name, x, envir = env) save(list = name, file = file, envir = env, ...) } list.savefile.rds <- function(x, file, ...) saveRDS(x, file, ...) rlist/R/list.table.R0000644000176200001440000000206013650064303013772 0ustar liggesusers#' Generate a table for a list by expression #' @param .data A \code{list} or \code{vector} #' @param ... A group of lambda expressions. If missing, #' \code{table} will be directly called upon \code{.data} with #' \code{table.args}. #' @param table.args \code{list}. The additional parameters #' passed to \code{table} #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.table(x, type) #' list.table(x, type, c1 = score$c1) #' list.table(x, type, score$c1, table.args = list(dnn=c('type','c1'))) list.table <- function(.data, ..., table.args = list(useNA = "ifany")) { if (missing(...)) return(do.call(table, c(list(.data), table.args))) args <- set_argnames(dots(...)) envir <- parent.frame() items <- lapply(args, function(arg) { values <- list.map.internal(.data, arg, envir) values[vapply(values, is.null, logical(1L))] <- NA c(values, recursive = TRUE) }) do.call(table, c(items, table.args)) } rlist/R/list.extract.R0000644000176200001440000000024313650064303014356 0ustar liggesusers#' Extract an element from a list or vector #' @export #' @examples #' x <- list(a=1, b=2, c=3) #' list.extract(x, 1) #' list.extract(x, 'a') list.extract <- `[[` rlist/R/subset.list.R0000644000176200001440000000174613650064303014222 0ustar liggesusers#' Subset a list by a logical condition #' #' @param x The list to subset #' @param subset A logical lambda expression of subsetting condition #' @param select A lambda expression to evaluate for each selected item #' @param ... Additional parameters #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' subset(x, type == 'B') #' subset(x, select = score) #' subset(x, min(score$c1, score$c2) >= 8, data.frame(score)) #' subset(x, type == 'B', score$c1) #' do.call(rbind, #' subset(x, min(score$c1, score$c2) >= 8, data.frame(score))) subset.list <- function(x, subset, select, ...) { envir <- parent.frame() subset.items <- if(missing(subset)) x else x[list.is.internal(x, substitute(subset), envir)] select.items <- if(missing(select)) subset.items else list.map.internal(subset.items, substitute(select), envir) list.clean(select.items) } rlist/R/list.find.R0000644000176200001440000000272113650064303013627 0ustar liggesusers#' Find a specific number of elements in a list or vector #' satisfying a given condition #' #' @param .data A \code{list} or \code{vector} #' @param cond A logical lambda expression #' @param n The number of items to find. (\code{n = 1L} by default) #' @return A list or vector of at most \code{n} elements in \code{.data} #' found to satisfy \code{cond}. #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.find(x, type=='B', 1) #' list.find(x, min(score$c1,score$c2) >= 9) list.find <- function(.data, cond, n = 1L) { .data[list.findi.internal(.data, substitute(cond), parent.frame(), n)] } #' Find the indices of a number of elements in a list or vector #' satisfying a given condition #' #' @param .data A \code{list} or \code{vector} #' @param cond A logical lambda expression #' @param n The number of items to find. (\code{n = 1L} by default) #' @return an integer vector consisting of the elements indices #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.findi(x, type=='B') #' list.findi(x, min(score$c1,score$c2) >= 8) #' list.findi(x, min(score$c1,score$c2) <= 8, n = 2) list.findi <- function(.data, cond, n = 1L) { list.findi.internal(.data, substitute(cond), parent.frame(), n) } rlist/R/lambda.R0000644000176200001440000000076113650064303013157 0ustar liggesuserslambda_symbols <- c(".", ".i", ".name") lambda_class <- "lambda_expression" lambda <- function(expr) { if (inherits(expr, lambda_class)) return(expr) if (is.formula(expr)) { if (length(expr) == 2L) return(Recall(expr[[2L]])) lhs <- expr[[2L]] expr <- expr[[3L]] lhs_symbols <- as.character(if (is.symbol(lhs)) lhs else lhs[-1L]) lambda_symbols[which(nzchar(lhs_symbols))] <- lhs_symbols } structure(list(expr = expr, symbols = lambda_symbols), class = lambda_class) } rlist/R/list.do.R0000644000176200001440000000402513650064303013310 0ustar liggesusers#' Call a function with a list of arguments #' #' @param .data \code{list}. \code{vector} will be coreced to \code{list} before #' being passed to \code{fun}. #' @param fun The \code{function} to call #' @param ... The additional parameters passed to \code{do.call} #' @export #' @examples #' x <- lapply(1:3, function(i) { c(a=i,b=i^2)}) #' df <- lapply(1:3, function(i) { data.frame(a=i,b=i^2,c=letters[i])}) #' list.do(x, rbind) list.do <- function(.data, fun, ...) { do.call(what = fun, args = as.list(.data), ...) } #' Bind all list elements by row #' #' The function binds all list elements by row. Each element of the list is expected #' to be an atomic vector, \code{data.frame}, or \code{data.table}. If list elements #' are also lists, the result can be a list-valued matrix. In this case, #' \code{list.stack} may produce a better result. #' #' @param .data \code{list} #' @export #' @seealso \code{\link{list.cbind}}, \code{\link{list.stack}} #' @examples #' x <- lapply(1:3,function(i) { c(a=i,b=i^2)}) #' df <- lapply(1:3,function(i) { data.frame(a=i,b=i^2,c=letters[i])}) #' list.rbind(x) #' list.rbind(df) list.rbind <- function(.data) { list.do(.data, "rbind") } #' Bind all list elements by column #' #' The function binds all list elements by column. Each element of the list is expected #' to be an atomic vector, \code{data.frame}, or \code{data.table} of the same length. #' If list elements are also lists, the binding will flatten the lists and may produce #' undesired results. #' #' @param .data \code{list} #' @export #' @seealso \code{\link{list.cbind}}, \code{\link{list.stack}} #' @examples #' x <- list(data.frame(i=1:5,x=rnorm(5)), #' data.frame(y=rnorm(5),z=rnorm(5))) #' list.cbind(x) list.cbind <- function(.data) { list.do(.data, "cbind") } #' Apply a function to each list element (\code{lapply}) #' @export #' @param .data A \code{list} or \code{vector} #' @param .fun \code{function} #' @param ... Additional parameters passed to \code{FUN}. list.apply <- function(.data, .fun, ...) lapply(X = .data, FUN = .fun, ...) rlist/R/list.update.R0000644000176200001440000000241313650064303014167 0ustar liggesusers#' Update a list by appending or modifying its elements. #' #' The function updates each element of a list by evaluating #' a group of expressions in the scope of the element. If the #' name of an expression alreadys exists in an list element, #' then the field with the name will be updated. Otherwise, #' the value with the name will be appended to the list #' element. The functionality is essentially done by #' \code{modifyList}. #' #' @param .data \code{list} #' @param ... A group of labmda expressions #' @param keep.null Should \code{NULL} values be preserved #' for \code{modifyList} #' @importFrom utils modifyList #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.update(x, high=max(score$c1,score$c2), low=min(score$c1,score$c2)) #' list.update(x, exams=length(score)) #' list.update(x, grade=ifelse(type=='A', score$c1, score$c2)) #' list.update(x, score=list(min=0, max=10)) list.update <- function(.data, ..., keep.null = FALSE) { items <- lapply(dots(...), list.map.internal, .data = .data, envir = parent.frame()) map(function(.data, ...) modifyList(.data, list(...), keep.null = keep.null), c(list(.data), items)) } rlist/R/list.insert.R0000644000176200001440000000342613650064303014216 0ustar liggesusers#' Insert a series of lists at the given index #' #' @param .data A \code{list} or \code{vector} #' @param index The index at which the lists are inserted #' @param ... A group of lists #' @export #' @seealso \code{\link{list.append}}, \code{\link{list.prepend}} #' @examples #' \dontrun{ #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.insert(x, 2, p2.1 = list(type='B',score=list(c1=8,c2=9))) #' } list.insert <- function(.data, index, ...) { values <- if (is.list(.data)) list(...) else c(..., recursive = FALSE) n <- length(.data) if (index < -n) stop("Invalid index") if (index < 0L) index <- n + index + 1L c(.data[0L:max(0L, index - 1L)], values, if (index <= n) .data[index:length(.data)] else NULL) } #' Append elements to a list #' #' @param .data A \code{list} or \code{vector} #' @param ... A \code{vector} or \code{list} to append after \code{x} #' @export #' @seealso \code{\link{list.prepend}}, \code{\link{list.insert}} #' @examples #' \dontrun{ #' x <- list(a=1,b=2,c=3) #' list.append(x,d=4,e=5) #' list.append(x,d=4,f=c(2,3)) #' } list.append <- function(.data, ...) { if (is.list(.data)) { c(.data, list(...)) } else { c(.data, ..., recursive = FALSE) } } #' Prepend elements to a list #' #' @param .data A \code{list} or \code{vector} #' @param ... The \code{vector} or \code{list} to prepend before \code{x} #' @export #' @seealso \code{\link{list.append}}, \code{\link{list.insert}} #' @examples #' x <- list(a=1,b=2,c=3) #' list.prepend(x, d=4, e=5) #' list.prepend(x, d=4, f=c(2,3)) list.prepend <- function(.data, ...) { if (is.list(.data)) { c(list(...), .data) } else { c(..., .data, recursive = FALSE) } } rlist/R/list.first.R0000644000176200001440000000257413650064303014044 0ustar liggesusers#' Find the first element that meets a condition #' @param .data A \code{list} or \code{vector} #' @param cond a logical lambda expression #' @export #' @seealso \code{\link{list.last}} #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.first(x, score$c1 < 10) #' list.first(x, score$c1 < 9 || score$c3 >= 5) # NULL for all results are NA or FALSE list.first <- function(.data, cond) { if (is.empty(.data)) return(NULL) if (missing(cond)) return(.data[[1L]]) res <- list.first.internal(.data, substitute(cond), parent.frame(), na.rm = TRUE) res$value } #' Find the last element that meets a condition #' @param .data A \code{list} or \code{vector} #' @param cond a logical lambda expression #' @seealso \code{\link{list.first}} #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.last(x, score$c1 < 10) #' list.last(x, score$c1 < 9 || score$c3 >= 5) # NULL for all results are NA or FALSE list.last <- function(.data, cond) { if (is.empty(.data)) return(NULL) if (missing(cond)) return(.data[[length(.data)]]) res <- list.first.internal(rev(.data), substitute(cond), parent.frame(), na.rm = TRUE) res$value } rlist/R/internal.R0000644000176200001440000001227713650064303013560 0ustar liggesusers.expr <- NULL map <- function(f, dots, more = NULL, use.names = TRUE) { res <- .mapply(f, dots, more) if (use.names && length(dots)) { if (!is.null(names1 <- names(dot1 <- dots[[1L]]))) names(res) <- names1 else if (is.character(dot1)) names(res) <- dot1 } res } reduce <- function(f, x, init, ...) { y <- init for (xi in x) y <- f(y, xi, ...) y } tryWithCondition <- function(expr, ...) { tryCatch(expr, condition = function(e) switch(e$message, ..., stop(e))) } list.map.fun <- function(.data, ., .i, .name) { eval(.expr, .evalwith(.data), environment()) } list.map.internal <- function(.data, expr, envir, fun = list.map.fun, args = NULL) { if (is.empty(.data)) return(list()) l <- lambda(expr) xnames <- getnames(.data, character(1L)) environment(fun) <- args_env(.expr = l$expr, .args = args, .evalwith = .evalwith, parent = envir) formals(fun) <- setnames(formals(fun), c(".data", l$symbols)) map(fun, list(.data, .data, seq_along(.data), xnames)) } list.is.fun <- function(.data, ., .i, .name) { x <- eval(.expr, .evalwith(.data), environment()) if (is.logical(x) && length(x) == 1L) x else NA } list.is.internal <- function(.data, cond, envir) { as.logical(list.map.internal(.data, cond, envir, list.is.fun)) } list.findi.fun <- function(.data, ., .i, .name) { .args$i <- .args$i + 1L x <- eval(.expr, .evalwith(.data), environment()) if (is.logical(x) && length(x) == 1L && !is.na(x)) { if (x) { .args$n <- .args$n + 1L .args$indices[[.args$n]] <- .args$i if (.args$n == .args$N) stop(simpleError("rlist.finished")) } } else if (.args$na.stop) stop(simpleError("rlist.stopped")) } list.findi.internal <- function(.data, cond, envir, n, na.stop = FALSE) { n <- min(n, length(.data)) args <- args_env(i = 0L, n = 0L, N = n, na.stop = na.stop, indices = integer(n)) tryWithCondition(list.map.internal(.data, cond, envir, list.findi.fun, args), rlist.finished = NULL, rlist.stopped = warning("Encountered value that is not TRUE or FALSE")) args$indices[0L:args$n] } list.first.fun <- function(.data, ., .i, .name) { x <- eval(.expr, .evalwith(.data), environment()) if (is.logical(x) && length(x) == 1L && !is.na(x)) { if (x) { .args$res <- list(state = TRUE, value = .data) stop(simpleError("rlist.finished")) } } else if (!.args$na.rm) { .args$res <- list(state = NA, value = .data) } } list.first.internal <- function(.data, cond, envir, na.rm) { args <- args_env(res = list(state = FALSE), na.rm = na.rm) tryWithCondition(list.map.internal(.data, cond, envir, list.first.fun, args), rlist.finished = NULL) args$res } list.while.fun <- function(.data, ., .i, .name) { x <- eval(.expr, .evalwith(.data), environment()) if (is.logical(x) && length(x) == 1L && !is.na(x) && x) .args$i <- .args$i + 1L else stop(simpleError("rlist.finished")) } list.order.internal <- function(.data, args, envir, na.last = TRUE) { if (is.empty(.data)) return(integer()) if (is.empty(args)) return(order(.data)) cols <- lapply(args, function(arg) { if (is.null(arg)) stop("NULL condition") desc <- class(arg) == "(" if (desc) arg <- arg[[2L]] col <- list.map.internal(.data, arg, envir) if (length(unique.default(vapply(col, "class", character(1L)))) > 1L) { warning("Inconsistent classes of values in column [", deparse(arg), "]. The column will be coerced to the same class.", call. = FALSE) } lens <- vapply(col, length, integer(1L)) if (any(lens != 1L)) { warning("Non-single value in column [", deparse(arg), "]. Use NA instead to order.", call. = FALSE) col[lens != 1L] <- NA } col <- unlist(col, recursive = FALSE, use.names = FALSE) if (desc) col <- -xtfrm(col) col }) do.call(order, c(cols, na.last = na.last)) } list.search.fun <- function(.data, .expr, .args, .n = .args$n, . = .data, .i = .args$i, .name = NULL) { .args$i <- .args$i + 1L q <- eval(.expr, NULL, environment()) vq <- !is.na(q) if (is.logical(q) && length(q) == 1L && !is.na(q)) { if (q) { .args$n <- .args$n + 1L .args$indices[[.args$n]] <- .args$i .args$result[[.args$n]] <- .data if (.args$n == .args$N) stop(simpleError("rlist.finished")) } } else if (length(q) >= 1L && any(vq)) { .args$n <- .args$n + 1L .args$indices[[.args$n]] <- .args$i .args$result[[.args$n]] <- q[vq] if (.args$n == .args$N) stop(simpleError("rlist.finished")) } } list.group.internal <- function(.data, keys, envir, proc = NULL, compare = "identical", sorted = TRUE) { if (is.empty(keys)) return(.data) values <- list.map.internal(.data, keys[[1L]], envir) proc <- if (!missing(proc) && !is.null(proc) && !is.function(proc)) match.fun(proc) else NULL uvalues <- if (is.function(proc)) proc(values) else values uniques <- unique.default(uvalues) names(uniques) <- uniques if (sorted && all(vapply(uniques, length, integer(1L)) == 1L)) uniques <- sort(c(uniques, recursive = TRUE)) lapply(uniques, function(key, ...) { selector <- vapply(values, compare, logical(1L), key, USE.NAMES = FALSE) list.group.internal(.data[selector], keys[-1L], ...) }, envir, proc, compare, sorted) } rlist/R/list.reverse.R0000644000176200001440000000032513650064303014360 0ustar liggesusers#' Reverse a list #' #' @param .data A \code{list} or \code{vector} #' @export #' @examples #' x <- list(a=1,b=2,c=3) #' list.reverse(x) list.reverse <- function(.data) { .data[rev.default(seq_along(.data))] } rlist/R/list.group.R0000644000176200001440000001147313650064303014047 0ustar liggesusers#' Divide list/vector elements into exclusive groups #' #' @param .data A \code{list} or \code{vector} #' @param ... One or more expressions in the scope of each element to evaluate #' as keys #' @param sorted \code{TRUE} to sort the group keys. Ignored when the key has #' multiple entries. #' @seealso \code{\link{list.ungroup}} #' @export #' @return A list of group elements each contain all the elements in \code{.data} #' belonging to the group #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.group(x, type) #' list.group(x, mean(unlist(score))) list.group <- function(.data, ..., sorted = TRUE) { list.group.internal(.data, dots(...), parent.frame(), compare = "identical", sorted = sorted) } #' Ungroup a list by taking out second-level elements #' #' This functon reverses the grouping operation by taking out #' second-level elements of a nested list and removing the labels #' of the first-level elements. For example, a list may be created #' from paged data, that is, its first-level elements only indicate #' the page container. To unpage the list, the first-level elements #' must be removed and their inner elements should be taken out to #' to the first level. #' @param .data \code{list} #' @param level {integer} to indicate to which level of list elements #' should be ungroupped to the first level. #' @param ... Preserved use of parameter passing #' @param group.names \code{logical}. Should the group names be #' preserved? #' @param sort.names \code{logical}. Should the members be sorted #' after ungrouping? #' @seealso \code{\link{list.group}} #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' xg <- list.group(x, type) #' list.ungroup(xg) #' #' x <- list(a = list(a1 = list(x=list(x1=2,x2=3),y=list(y1=1,y2=3))), #' b = list(b1 = list(x=list(x1=2,x2=6),y=list(y1=3,y2=2)))) #' list.ungroup(x, level = 1) #' list.ungroup(x, level = 2) #' list.ungroup(x, level = 2, group.names = TRUE) list.ungroup <- function(.data, level = 1L, ..., group.names = FALSE, sort.names = FALSE) { result <- .data for(i in seq_len(level)) { if(!group.names) names(result) <- NULL result <- unlist(result, recursive = FALSE) } result.names <- names(result) if (sort.names && !is.null(result.names)) { result[sort(result.names)] } else { result } } #' Classify list elments into unique but non-exclusive cases #' #' In non-tabular data, a certain field may take multiple values in a #' collection non-exclusively. To classify these elements into different #' cases, this function detects all possible cases and for each case all #' elements are examined whether to belong to that case. #' @param .data A \code{list} or \code{vector} #' @param ... keys #' @param sorted \code{TRUE} to sort the group keys. Ignored when the key has #' multiple entries. #' @export #' @return a list of possible cases each of which contains elements belonging to #' the case non-exclusively. #' @examples #' x <- #' list( #' p1=list(name='Ken',age=24, #' interest=c('reading','music','movies'), #' lang=list(r=2,csharp=4,python=3)), #' p2=list(name='James',age=25, #' interest=c('sports','music'), #' lang=list(r=3,java=2,cpp=5)), #' p3=list(name='Penny',age=24, #' interest=c('movies','reading'), #' lang=list(r=1,cpp=4,python=2))) #' list.class(x,interest) #' list.class(x,names(lang)) list.class <- function(.data, ..., sorted = TRUE) { list.group.internal(.data, dots(...), parent.frame(), proc = "unlist", compare = "contains", sorted = sorted) } #' Get all unique cases of a list field by expression #' #' @param .data A \code{list} or \code{vector} #' @param expr A lambda expression. The function will returns all cases #' of the elements if \code{expr} is missing. #' @param simplify \code{logical}. Should atomic vectors be simplified #' by \code{unlist}? #' @param sorted \code{logical}. Should the cases be sorted in ascending order? #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.cases(x,type) #' list.cases(x,mean(unlist(score))) #' #' foo <- list(x = LETTERS[1:3], y = LETTERS[3:5]) #' list.cases(foo) list.cases <- function(.data, expr, simplify = TRUE, sorted = TRUE) { expr <- if(missing(expr)) quote(.) else substitute(expr) values <- list.map.internal(.data, expr, parent.frame()) if (simplify && all(vapply(values, is.atomic, logical(1L)))) { values <- c(values, recursive = TRUE) } cases <- unique(values) if (sorted && is.atomic(cases)) cases <- sort(cases) cases } rlist/R/List.R0000644000176200001440000001352613650064303012655 0ustar liggesuserscreateListClosure <- function(f, data) { f <- substitute(f) function(...) { dots <- match.call(expand.dots = FALSE)$... rcall <- as.call(c(f, quote(data), dots)) data <- eval(rcall, list(data = data), parent.frame()) List(data) } } createCallClosure <- function(data) { function(f, ...) { f <- substitute(f) dots <- match.call(expand.dots = FALSE)$... rcall <- as.call(c(f, quote(data), dots)) data <- eval(rcall, list(data = data), parent.frame()) List(data) } } #' Create a \code{List environment} that wraps given \code{data} and #' most list functions are defined for chainable operations. #' #' @param data A \code{list} or \code{vector} #' @export #' @details #' Most list functions are defined in \code{List environment}. #' In addition to these functions, \code{call(fun,...)} calls #' external function \code{fun} with additional parameters specifies in #' \code{...}. #' #' To extract the data from List \code{x}, call \code{x$data} or simply #' \code{x[]}. #' #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' m <- List(x) #' m$filter(type=='B')$ #' map(score$c1) [] #' #' m$group(type)$ #' map(g ~ List(g)$ #' map(score)$ #' call(unlist)$ #' call(mean) []) [] #' #' # Subsetting, extracting, and assigning #' #' p <- List(list(a=1,b=2)) #' p['a'] #' p[['a']] #' p$a <- 2 #' p['b'] <- NULL #' p[['a']] <- 3 List <- function(data = list()) { call <- createCallClosure(data) all <- createListClosure(list.all, data) any <- createListClosure(list.any, data) append <- createListClosure(list.append, data) apply <- createListClosure(list.apply, data) cases <- createListClosure(list.cases, data) cbind <- createListClosure(list.cbind, data) class <- createListClosure(list.class, data) clean <- createListClosure(list.clean, data) common <- createListClosure(list.common, data) count <- createListClosure(list.count, data) do <- createListClosure(list.do, data) exclude <- createListClosure(list.exclude, data) extract <- createListClosure(list.extract, data) filter <- createListClosure(list.filter, data) find <- createListClosure(list.find, data) findi <- createListClosure(list.findi, data) first <- createListClosure(list.first, data) flatten <- createListClosure(list.flatten, data) group <- createListClosure(list.group, data) is <- createListClosure(list.is, data) insert <- createListClosure(list.insert, data) iter <- createListClosure(list.iter, data) join <- createListClosure(list.join, data) last <- createListClosure(list.last, data) load <- createListClosure(list.load, data) map <- createListClosure(list.map, data) mapv <- createListClosure(list.mapv, data) match <- createListClosure(list.match, data) merge <- createListClosure(list.merge, data) names <- createListClosure(list.names, data) order <- createListClosure(list.order, data) parse <- createListClosure(list.parse, data) prepend <- createListClosure(list.prepend, data) rbind <- createListClosure(list.rbind, data) remove <- createListClosure(list.remove, data) reverse <- createListClosure(list.reverse, data) sample <- createListClosure(list.sample, data) save <- createListClosure(list.save, data) search <- createListClosure(list.search, data) select <- createListClosure(list.select, data) serialize <- createListClosure(list.serialize, data) skip <- createListClosure(list.skip, data) skipWhile <- createListClosure(list.skipWhile, data) sort <- createListClosure(list.sort, data) stack <- createListClosure(list.stack, data) table <- createListClosure(list.table, data) take <- createListClosure(list.take, data) takeWhile <- createListClosure(list.takeWhile, data) ungroup <- createListClosure(list.ungroup, data) unserialize <- createListClosure(list.unserialize, data) upzip <- createListClosure(list.unzip, data) update <- createListClosure(list.update, data) which <- createListClosure(list.which, data) zip <- createListClosure(list.zip, data) subset <- createListClosure(list.subset, data) envir <- environment() setclass(envir, c("List", "environment")) } #' @export print.List <- function(x, ..., header = getOption("List.header", TRUE)) { if (!is.null(x$data)) { if (header) cat("$data :", class(x$data), "\n------\n") print(x$data, ...) } } #' @importFrom utils str #' @export str.List <- function(object, ..., header = getOption("List.header", TRUE)) { if (header) cat("$data : ") str(object$data, ...) } #' @export summary.List <- function(object, ...) { summary(object$data, ...) } #' @export `==.List` <- function(e1, e2) { e1$data == e2 } #' @export subset.List <- function(x, ...) { subset(x$data, ...) } ndots <- function(dots) { length(dots) >= 1L && any(nzchar(dots)) } List_get <- function(f, data, dots, envir) { if (!ndots(dots)) return(data) rcall <- as.call(c(f, quote(data), dots)) data <- eval(rcall, list(data = data), envir) List(data) } List_get_function <- function(op) { op <- as.symbol(op) function(x, ...) { dots <- match.call(expand.dots = FALSE)$... List_get(op, x$data, dots, parent.frame()) } } #' @export `[.List` <- List_get_function("[") #' @export `[[.List` <- List_get_function("[[") List_set <- function(f, x, dots, value, envir) { if (!ndots(dots)) return(value) rcall <- as.call(c(f, quote(x), dots, quote(value))) data <- eval(rcall, list(x = x, value = value), envir) List(data) } List_set_function <- function(op) { op <- as.symbol(op) function(x, ..., value) { dots <- match.call(expand.dots = FALSE)$... List_set(op, x$data, dots, value, parent.frame()) } } #' @export `$<-.List` <- List_set_function("$<-") #' @export `[<-.List` <- List_set_function("[<-") #' @export `[[<-.List` <- List_set_function("[[<-") rlist/R/list.merge.R0000644000176200001440000000250413650064303014005 0ustar liggesusers#' Merge a number of named lists in sequential order #' #' The function merges a number of lists in sequential order #' by \code{modifyList}, that is, the later list always #' modifies the former list and form a merged list, and the #' resulted list is again being merged with the next list. #' The process is repeated until all lists in \code{...} or #' \code{list} are exausted. #' #' @details #' List merging is usually useful in the merging of program #' settings or configuraion with multiple versions across time, #' or multiple administrative levels. For example, a program #' settings may have an initial version in which most keys are #' defined and specified. In later versions, partial modifications #' are recorded. In this case, list merging can be useful to merge #' all versions of settings in release order of these versions. The #' result is an fully updated settings with all later modifications #' applied. #' @param ... named lists #' @importFrom utils modifyList #' @export #' @examples #' l1 <- list(a=1,b=list(x=1,y=1)) #' l2 <- list(a=2,b=list(z=2)) #' l3 <- list(a=2,b=list(x=3)) #' list.merge(l1,l2,l3) list.merge <- function(...) { lists <- list(...) if (any(vapply(lists, function(x) is.null(names(x)), logical(1L)))) stop("All arguments must be named list", call. = FALSE) reduce(modifyList, lists, list()) } rlist/R/list.select.R0000644000176200001440000000122213650064303014161 0ustar liggesusers#' Select by name or expression for each member of a list #' #' @param .data A \code{list} or \code{vector} #' @param ... A group of implicit labmda expressions #' @export #' @examples #' x <- list(p1 = list(type='A',score=list(c1=10,c2=8)), #' p2 = list(type='B',score=list(c1=9,c2=9)), #' p3 = list(type='B',score=list(c1=9,c2=7))) #' list.select(x, type) #' list.select(x, tp = type) #' list.select(x, type, score) #' list.select(x, type, score.range = range(unlist(score))) list.select <- function(.data, ...) { args <- set_argnames(dots(...)) quote <- as.call(c(quote(list), args)) list.map.internal(.data, quote, parent.frame()) } rlist/R/list.flatten.R0000644000176200001440000000214714114255657014360 0ustar liggesusers#' Flatten a nested list to a one-level list #' #' @details #' The function is essentially a slightly modified version of \code{flatten2} #' provided by Tommy at \href{https://stackoverflow.com/a/8139959/2906900}{stackoverflow.com} who #' has full credit of the implementation of this function. #' @param x \code{list} #' @param use.names \code{logical}. Should the names of \code{x} be kept? #' @param classes A character vector of class names, or "ANY" to match any class. #' @author \href{https://stackoverflow.com/users/662787/tommy}{Tommy} #' @export #' @examples #' p <- list(a=1,b=list(b1=2,b2=3),c=list(c1=list(c11='a',c12='x'),c2=3)) #' list.flatten(p) #' #' p <- list(a=1,b=list(x="a",y="b",z=10)) #' list.flatten(p, classes = "numeric") #' list.flatten(p, classes = "character") list.flatten <- function(x, use.names = TRUE, classes = "ANY") { len <- sum(rapply(x, function(x) 1L, classes = classes)) y <- vector("list", len) i <- 0L items <- rapply(x, function(x) { i <<- i + 1L y[[i]] <<- x TRUE }, classes = classes) if (use.names && !is.null(nm <- names(items))) names(y) <- nm y } rlist/MD50000644000176200001440000001607214114411362011722 0ustar liggesusers01eda0a50a5d2cf7aaa0e113f183fcdb *DESCRIPTION 1640b584abec3227f9ee11b460e4d58f *LICENSE 1fb954d5ce290d7d43fd9acbaf5342b0 *NAMESPACE 854515220942e2f9dce9ec57c25b7e2d *NEWS c5e4d06dfbf96f5715f5385f76772570 *R/List.R 36c34f9f80f04412fa3316114204f4d7 *R/data.R b5cf658b72e67f5d5b42058ed9d73268 *R/functions.R eaf622c75efaa63e2a2723dd4b358622 *R/internal.R 384fa2c1647e4c67d79e4e85ec951e79 *R/lambda.R e5b7794bd8a598cce42faef620bb7a7f *R/list.all.R 2388eb2284a484dd8539109ebb9a64d2 *R/list.clean.R ad16c301316c42b581f434840b5bb96c *R/list.common.R 50738631d0327aee6e28c74537e7d2e4 *R/list.count.R 5efc6d2c219a60f28389f4efbb8c5ebf *R/list.do.R a160c92e08cfc5ada328fbe3dc3f0d5a *R/list.expand.R 475b286033ef4a5a7c4f6f050c892dbd *R/list.extract.R 8287c37dd2299d7bf0a0ea22e2c79237 *R/list.filter.R 88f68b01a72815801b55db0df74422f7 *R/list.find.R 76461b4327aa259379a3fe42de45556b *R/list.first.R fb376190a79dacd091a6b6f68a48d3d8 *R/list.flatten.R b568a26983e6c3f9f022d46c4ac80139 *R/list.group.R 8e66b2468a2c245cfc97d189d5d0f119 *R/list.insert.R 8b0a39263f7085227f42d3d6acc1df2b *R/list.is.R a40cbd959d0f863afb7b344e835aa40b *R/list.join.R 25f163f5a96b4c336353d72b9cabf5f0 *R/list.load.R 814ff5ed429eac136775738baea622d3 *R/list.map.R d7b21cb8820de92f622f45a061ba9e1f *R/list.match.R 534ed3d9b0f33ced23c73f7696621160 *R/list.merge.R 36100282f5553a86ffe4082d477215b7 *R/list.names.R fe7e6c8cbc839d9d5b12443ee20993a2 *R/list.order.R a9e432afef9d4e3935f20702934abafa *R/list.parse.R a5f028d57de76112cbb2b1650b4fb27f *R/list.remove.R 2dcdf8ca99e42435ada061685f9e29a8 *R/list.reverse.R f2cb5d69bae85726517185a34f007786 *R/list.sample.R fd411a799f3448993fd741f0701fd7a4 *R/list.save.R c67eea812337d538e5abd8f417f7e4e0 *R/list.search.R 5d748463d1a16c12e2c1259637a01e9b *R/list.select.R 7712dfb0ba7dec405b5d93bfe0761d49 *R/list.serialize.R f94bac61447b669dc2d7f644d6c01907 *R/list.skip.R cebd2fc7c02c9e609316fe904714536e *R/list.stack.R c2512cf7df44af7632cd3c6368010da4 *R/list.subset.R 57f18df7485b1c358d6301fe67b064d7 *R/list.table.R bbe443e8c59a12e7ef2b707b84474a1b *R/list.take.R c9231526a200a59b9c8d084cf9138cf5 *R/list.update.R 7dfaf97b77056b9b2ffc194ea1160c17 *R/list.which.R 1eb01505ca3b1b4c1a8dbe9dbaa9683f *R/list.zip.R 68d446beffa8091575ce916868f65576 *R/rlist.R 1307f615a69bbe9be778d19069c6ec59 *R/subset.list.R 626e7dbe16dce5861b648b212350a1f5 *R/utils.R 72f5ae8a5a807534646aeeffd5f5443a *README.md ee6b654954dc06fd53ba6a6fec4dce85 *data/nyweather.rda 346ae41c9accb5320d4fcef630625443 *man/List.Rd 5fdc75b32f811686d393530e59ca53f6 *man/args_env.Rd 2312cd99b5fed445f9eeffba9ebad9b6 *man/args_list.Rd 3b249c3e41469a98e033beeb1139e4dc *man/callwith.Rd 2f6a8cd82009c9271e3d8d41c0736536 *man/contains.Rd 24fbb4f0c512210cbdf3f2b0e7e8c466 *man/dot-evalwith.Rd 7a37065db7b812c510765b05c0231d8a *man/dots.Rd 2f365505d2d42db96bf2c26be21d68ad *man/getnames.Rd 7d475e48714fc4f64d6f4ab37f403747 *man/is.empty.Rd 2b61f7a3851009b3d2d7a11b13fdcc0d *man/list.all.Rd 46de72fbec9f1b087963c2f0c666e39f *man/list.any.Rd ba92853bd608f61878892ede8991c4a1 *man/list.append.Rd 842f8e8a2706a02fd0686d0f258c3899 *man/list.apply.Rd 7d77102fe409b554fb3157cd880a7bb7 *man/list.cases.Rd 229cf73f2087e32261d460934ae74912 *man/list.cbind.Rd 3687b7f87e7417e544ec4825bfc57ad7 *man/list.class.Rd 2a103a9974fb020e6415a88f03c61e01 *man/list.clean.Rd 6758553d77c75c879a7686a87590ac25 *man/list.common.Rd 379157e774fe49e9d95be226977e1c0d *man/list.count.Rd b78675ce6070f9ee4d65cf087f7635b3 *man/list.do.Rd 0cf5545e40bf4c4a1dff30d346acd639 *man/list.exclude.Rd c3a5dba2f08e8ef91bd222207ec7d6cb *man/list.expand.Rd 913c2f61ebba3dbb2bdcf4760440279e *man/list.extract.Rd 7f041056b79bf86e1f73c1dcbd916946 *man/list.filter.Rd fa6fd435cbe715e735e8cb774479c564 *man/list.find.Rd 34f2321b3dee5979e26d01c06871da63 *man/list.findi.Rd 789b08053504000dc48b06e23eb2ddc7 *man/list.first.Rd 6630eb077972a7864b7a5fb1ee11db0a *man/list.flatten.Rd 2b9b9baeb03f93cb2c65021d41713686 *man/list.group.Rd a7c47a300bacdf6f7afbf0a31c7be9aa *man/list.insert.Rd be4645a038bf4b6e7b07fc007272946d *man/list.is.Rd 911f62505d245e432c8bacff5bae6759 *man/list.iter.Rd 525e5dcddac81eb6f25a719073812959 *man/list.join.Rd fd906743550ce55017b3c7c11189ca7c *man/list.last.Rd 580ae41fb74e4c8c6732c18d39513cd4 *man/list.load.Rd 2843376337bed020059636f491202459 *man/list.map.Rd 925866c3857e7e946b365eb7976cd251 *man/list.maps.Rd 24951d56ec0717b74785033b78bb5c15 *man/list.mapv.Rd 9c5bde918aa046bbd536cce728674837 *man/list.match.Rd dc0ce556f38836a47e2b09985fe45f22 *man/list.merge.Rd 5e588140b1a1e6ff8a87e1c1cfd60fd1 *man/list.names.Rd ad703b4bfa8bae75516f175425967dea *man/list.order.Rd df2c71525ee14fa3a789956e39361a60 *man/list.parse.Rd 5554ce2c5924d1ee447c2a9bb4bf9435 *man/list.prepend.Rd ed7f41d0935421e86c332b50e5f9ac52 *man/list.rbind.Rd 63e4b1d2191adf10c674e05e846d5da4 *man/list.remove.Rd c53d4dc7f37a275a69feaf07c3600533 *man/list.reverse.Rd 5aa2ef81eebc21a0ddfe4eb16077eb4b *man/list.sample.Rd a1414945b035b6b130a5ffcdb806f660 *man/list.save.Rd 9ed766f8d926b59f02b22d8abc1d0c66 *man/list.search.Rd 1792c6b451ec497bed90234f2c7324ab *man/list.select.Rd deb596bec3e710f272a2eddb2c235ab3 *man/list.serialize.Rd a76659592b1c26040de3e1f66aaf64e0 *man/list.skip.Rd 4f5a5013cff6d0a044e8b8abf42a6251 *man/list.skipWhile.Rd 445faccf5a46294285ed33b61c4179cb *man/list.sort.Rd 66aa17f38de69fc8c2109002ec44ac57 *man/list.stack.Rd 4ccb0c5acf23cc822dc6570bf85b3eea *man/list.subset.Rd 55ac339e95d8e9b7b4af4fdf3e687b67 *man/list.table.Rd 28db0d59b3f1dfc9795658c536f25982 *man/list.take.Rd 4e80c6d711a19d2663cff0ba158e5837 *man/list.takeWhile.Rd 425ac2b71a1ef86f4b6ac161dac5c6af *man/list.ungroup.Rd 62bc360eac75f4b85e0b0a9bc40a77bb *man/list.unserialize.Rd d4ed72816ae4af67a212cc78dae8cd81 *man/list.unzip.Rd f5977b05c4124cda8fe84ed8a9362774 *man/list.update.Rd c31ae8f5043b2d097dda286988c3df0a *man/list.which.Rd ba9d98a250486c3dee6c594ea92a17be *man/list.zip.Rd 2a57b7ac9a92b84cd71250b0f1690084 *man/nyweather.Rd 005c312f4472af8d7331792fa7685430 *man/rlist-package.Rd aaa46b791c48e1cac2ff2561083a32a5 *man/set_argnames.Rd a3764fcf40ed4448fba3e47653a10a24 *man/subset.list.Rd 594436af54fea77bdcca56cea6895263 *man/tryEval.Rd 38355387d4a4d95a9f7f2d2969f5298e *man/tryGet.Rd 8c4d3a33eede57b7dbfd2dca9205ccd8 *tests/testthat.R f0b031e3537494b40f95fdc33bec3f63 *tests/testthat/test-List.R c7cc17fa11363ef5a9e3d4ff999061d0 *tests/testthat/test-basic.R 54faaadbd79b59428917d990eeb4fc83 *tests/testthat/test-class.R a3f0b13e3d372eb1b6db9b22924a3c71 *tests/testthat/test-filter.R c9d932a24f9e957dcf26194162dfa476 *tests/testthat/test-find.R aaf6c2f654441c10db283ebc4441a082 *tests/testthat/test-group.R 6ec37ab149f1042cfff091b0c2f146ae *tests/testthat/test-internal.R ee98664619ad45634926b761f6b3f48a *tests/testthat/test-io.R 861c5dac8d9df3f2a4739077b792fa91 *tests/testthat/test-join.R 7f8c8e8e333430c20b957e8272694070 *tests/testthat/test-map.R e52c576ee7d668b7f8123fc2a32bab1a *tests/testthat/test-search.R d7b5f849f27671f68d81a679836875d0 *tests/testthat/test-select.R 86d9f2d719b6570cea51c5567d085302 *tests/testthat/test-sort.R f733d402e556d29156d976aa252ca39c *tests/testthat/test-subset.R 6a2903c8010b6d98e6117df5580c342c *tests/testthat/test-update.R 270f98c244a9dc35b5d16a3e553231c5 *tests/testthat/test-utils.R