Dear Bert, First off, I want to thank you for the many hundreds (if not thousands) of excellent posts I've read from you on this mailing list over the years. And you are absolutely correct that when using the `%%` modulo operator, your code is the most compact and the most idiomatic.
That being said, if someone coming from another programming language is posting code on this mailing list using a `for()` loop, they may be most comfortable getting working code back from this mailing-list that still uses a `for()` loop in R. Furthermore, people often start by *filtering* their data, when a better approach might be to first *recode* it, for which the `ifelse()` function provides a nice solution. But of course, a more simple approach than I previously posted would be below (although less idiomatic than your answer): > object <- 1:100 > index <- ifelse(object %% 2 == 1, TRUE, FALSE) > object[index] [1] 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 [30] 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 > This brings us to the question of programming 'philosophy': certain languages advise "TMTOWTDI", while another advises "There should be one--and preferably only one--obvious way to do it." Where does R fit on this spectrum? I believe one of R's underappreciated strengths is being more in-line with the "TMTOWTDI" principle. So people coming from other languages can get good results right off the bat using vectorized indexing/filtering, or for() loops, or the apply() family of functions, or writing a custom function (all answers given in this thread). Finally, if a nascent R programmer ever ventures into filtering their data using objects and indexes of different lengths, they should have a grasp of the code examples below (recycling rule): long_vec <- 1:16 print(long_vec) short_vec <- rep(4,8) print(short_vec) print(long_vec[long_vec > short_vec]) span <- 1:length(short_vec) print(long_vec[span][long_vec[span] > short_vec]) print(long_vec[span][long_vec > short_vec]) Best Regards, Bill. W. Michels, Ph.D. On Sat, Jun 5, 2021 at 12:26 PM Bert Gunter <bgunter.4...@gmail.com> wrote: > > I'm sorry, but this is a good example of how one should *not* do this in R. > I also should apologize for any pedantry that follows, but I believe this > serves as a nice example of the ideas. > > Two of R's central features as a "data science" language are that many of its > core capabilities are "vectorized" -- can calculate on whole objects (at the > user-visible interpreter level) rather than requiring explicit loops; and > that it can use object indexing in several different modalities, here logical > indexing, for extraction and replacement in whole objects such as vectors and > matrices. Not only does this typically yield simpler, more readable code > (admittedly, a subjective judgment), but it is also typically much faster, > though I grant you that this can often be overrated. > > In this instance, the several lines of looping code you presented can be > condensed into a single line: > > > span <- 1:20 > > span[span %% 2 == 1] > [1] 1 3 5 7 9 11 13 15 17 19 > > ### Trickier, but perhaps instructive, is: ### > > span[TRUE & span %% 2] > [1] 1 3 5 7 9 11 13 15 17 19 > > All languages trade off various strengths and weaknesses, but I think it's > fair to say that one should try to work within the paradigms that are the > language's strengths when possible, R's vectorization and indexing in this > example. > > Cheers, > Bert Gunter > > "The trouble with having an open mind is that people keep coming along and > sticking things into it." > -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) > > > On Sat, Jun 5, 2021 at 11:05 AM William Michels via R-help > <r-help@r-project.org> wrote: >> >> > i <- 1L; span <- 1:100; result <- NA; >> > for (i in span){ >> + ifelse(i %% 2 != 0, result[i] <- TRUE, result[i] <- FALSE) >> + } >> > span[result] >> [1] 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 >> 45 47 49 51 53 55 57 >> [30] 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 >> > >> >> HTH, Bill. >> >> W. Michels, Ph.D. >> >> >> On Sat, Jun 5, 2021 at 12:55 AM Stefan Evert <stefa...@collocations.de> >> wrote: >> > >> > > >> > > I don't understand. -- >> > > >> > > 7%%2=1 >> > > 9%%2=1 >> > > 11%%2=1 >> > > >> > > What aren't these numbers printing ? >> > > >> > > num<-0 >> > > for (i in 1:100){ >> > > num<-num+i >> > > if (num%%2 != 0) >> > > print(num) >> > > } >> > >> > Your code tests the numbers >> > >> > 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, … >> > >> > and correctly prints the odd ones among them. >> > >> > But I suppose that's not what you wanted to do? >> > >> > ______________________________________________ >> > R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see >> > https://stat.ethz.ch/mailman/listinfo/r-help >> > PLEASE do read the posting guide >> > http://www.R-project.org/posting-guide.html >> > and provide commented, minimal, self-contained, reproducible code. >> >> ______________________________________________ >> R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code. ______________________________________________ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.