www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Working with ranges

reply Murilo <murilomiranda92 hotmail.com> writes:
Hi guys, I have created an array of strings with "string[12] ps = 
["cat", "dog", "lion", "wolf", "coin", "chest", "money", "gold", 
"A", "B", "C", "D"];".


I want to use the array as a range and I want to randomize it, 
like I want to transform that into several other ranges with the 
same elements but in different orders, how do I do that?

I tried using the function choice() from std.random but it gives 
an error message for some reason.
Dec 07 2018
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 8 December 2018 at 03:37:56 UTC, Murilo wrote:
 Hi guys, I have created an array of strings with "string[12] ps
string[12] isn't a range, but string[] is. Try passing `ps[]` to the function instead of plain `ps` and see what happens.
Dec 07 2018
next sibling parent reply Murilo <murilomiranda92 hotmail.com> writes:
On Saturday, 8 December 2018 at 03:46:11 UTC, Adam D. Ruppe wrote:
 On Saturday, 8 December 2018 at 03:37:56 UTC, Murilo wrote:
 Hi guys, I have created an array of strings with "string[12] ps
string[12] isn't a range, but string[] is. Try passing `ps[]` to the function instead of plain `ps` and see what happens.
How do I transform an array into a range?
Dec 07 2018
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 8 December 2018 at 03:48:10 UTC, Murilo wrote:
 Try passing `ps[]` to the function instead of plain `ps` and 
 see what happens.
How do I transform an array into a range?
With the slicing operator, [].
Dec 07 2018
next sibling parent reply Murilo <murilomiranda92 hotmail.com> writes:
On Saturday, 8 December 2018 at 03:51:02 UTC, Adam D. Ruppe wrote:
 On Saturday, 8 December 2018 at 03:48:10 UTC, Murilo wrote:
 Try passing `ps[]` to the function instead of plain `ps` and 
 see what happens.
How do I transform an array into a range?
With the slicing operator, [].
Thank you very much, it worked now. What is the difference between declaring "int[3] a = [1,2,3];" and declaring "int[] a = [1,2,3];"? Is the first an array and the second a range? I always thought that leaving the square brackets empty would create an array of flexible size, it never occurred to me that it was creating something else.
Dec 07 2018
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 8 December 2018 at 04:11:03 UTC, Murilo wrote:
 What is the difference between declaring "int[3] a = [1,2,3];" 
 and declaring "int[] a = [1,2,3];"? Is the first an array and 
 the second a range?
They are both arrays, just the former one has a fixed size and the latter does not. Ranges require a way to iterate and consume elements, meaning they cannot be fixed size.
 I always thought that leaving the square brackets empty would 
 create an array of flexible size, it never occurred to me that 
 it was creating something else.
That's what it is, just a flexible array also happens to be an array, whereas a fixed-size array is not one. But a slice of a fixed size one yields a flexible one.. which is why the ps[] thing works to create a range out of it.
Dec 07 2018
next sibling parent reply Murilo <murilomiranda92 hotmail.com> writes:
On Saturday, 8 December 2018 at 04:16:25 UTC, Adam D. Ruppe wrote:
 On Saturday, 8 December 2018 at 04:11:03 UTC, Murilo wrote:
 What is the difference between declaring "int[3] a = [1,2,3];" 
 and declaring "int[] a = [1,2,3];"? Is the first an array and 
 the second a range?
They are both arrays, just the former one has a fixed size and the latter does not. Ranges require a way to iterate and consume elements, meaning they cannot be fixed size.
 I always thought that leaving the square brackets empty would 
 create an array of flexible size, it never occurred to me that 
 it was creating something else.
That's what it is, just a flexible array also happens to be an array, whereas a fixed-size array is not one. But a slice of a fixed size one yields a flexible one.. which is why the ps[] thing works to create a range out of it.
Thank you guys so much for the explanation, it is all making more sense now.
Dec 07 2018
parent Murilo <murilomiranda92 hotmail.com> writes:
Hi guys, thank you for helping me out here, there is this 
facebook group for the D language, here we can help and teach 
each other. It is called Programming in D. Please join. 
https://www.facebook.com/groups/662119670846705/?ref=bookmarks
Dec 09 2018
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 12/7/18 11:16 PM, Adam D. Ruppe wrote:
 On Saturday, 8 December 2018 at 04:11:03 UTC, Murilo wrote:
 What is the difference between declaring "int[3] a = [1,2,3];" and 
 declaring "int[] a = [1,2,3];"? Is the first an array and the second a 
 range?
They are both arrays, just the former one has a fixed size and the latter does not. Ranges require a way to iterate and consume elements, meaning they cannot be fixed size.
 I always thought that leaving the square brackets empty would create 
 an array of flexible size, it never occurred to me that it was 
 creating something else.
That's what it is, just a flexible array also happens to be an array, whereas a fixed-size array is not one.
I think, you mean "a flexible array also happens to be *a range*..." -Steve
Dec 09 2018
prev sibling parent reply Elmar <chrehme gmx.de> writes:
On Saturday, 8 December 2018 at 03:51:02 UTC, Adam D. Ruppe wrote:
 On Saturday, 8 December 2018 at 03:48:10 UTC, Murilo wrote:
 Try passing `ps[]` to the function instead of plain `ps` and 
 see what happens.
How do I transform an array into a range?
With the slicing operator, [].
That's amazing, this should be one thing that should appear in every tutorial just right at the start! I was looking hours for a way to generate an "iterator" (a range) from a fixed-size array which doesn't copy the elements (unless elements are deleted/added). But my issue now is, I have strided arrays (or just any Result range) and I want to use the slicing operator `[]` with that range to copy it into a fixed-size array or apply element-wise operations on it. How can I do that? This example will not compile: ``` auto starts = arr[0..$].stride(2); auto ends = arr[1..$].stride(2); randomNumbers[] = ends[] - starts[]; ``` Because `[]` is not defined for the Result range. Is there a standard wrapper function which wraps an elementwise `[]` operator implementation around a range?
May 26
next sibling parent reply Jack <jckj33 gmail.com> writes:
On Wednesday, 26 May 2021 at 13:58:56 UTC, Elmar wrote:
 On Saturday, 8 December 2018 at 03:51:02 UTC, Adam D. Ruppe 
 wrote:
 [...]
That's amazing, this should be one thing that should appear in every tutorial just right at the start! I was looking hours for a way to generate an "iterator" (a range) from a fixed-size array which doesn't copy the elements (unless elements are deleted/added). [...]
maybe array from std.array to make that range in array of its own?
May 26
next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 5/26/21 8:07 AM, Jack wrote:

 maybe array from std.array to make that range in array of its own?
Yes, something like this: import std; void main() { auto arr = 10.iota.map!(i => uniform(0, 100)); auto starts = arr[0..$].stride(2); auto ends = arr[1..$].stride(2); auto randomNumbers = zip(ends, starts) .map!(t => t[0] - t[1]) .array; // <-- Only when necessary writeln(randomNumbers); } Ali
May 26
prev sibling parent reply Elmar <chrehme gmx.de> writes:
On Wednesday, 26 May 2021 at 15:07:12 UTC, Jack wrote:
 On Wednesday, 26 May 2021 at 13:58:56 UTC, Elmar wrote:
 On Saturday, 8 December 2018 at 03:51:02 UTC, Adam D. Ruppe 
 wrote:
 [...]
That's amazing, this should be one thing that should appear in every tutorial just right at the start! I was looking hours for a way to generate an "iterator" (a range) from a fixed-size array which doesn't copy the elements (unless elements are deleted/added). [...]
maybe array from std.array to make that range in array of its own?
The main incentive here is, that I would like to obtain an iterator (some kind of access view) over a background storage which can be anywhere in memory which I don't care about. It might be on stack frame. In many or most of the cases the use case doesn't actually require GC-allocation. `array()` does GC-allocation and personally, I think `array()` should be avoided whereever the use case doesn't justify GC-allocation, at least if you care for *logically correct* memory management of your program. GC-allocation might just work the same way (most of the time even better than with stack-allocated storage due to design of D) and it adds convenience for you to omit explicit destruction calls which can spare you some conditional checks if the need for destruction depends on runtime cases. But with logical correctness I mean appropriateness here, an allocation scheme which reflects the nature of a variable's lifetime correctly. For example, if the lifetime, maximum storage requirements or the de-/allocation points in code are already known at compile-time then GC-allocation isn't appropriate. It has many drawbacks in performance critical sections, such as non-deterministic destruction time (which probably is the worst), the overhead of scanning GC-allocated regions and the memory fragmentation caused by dynamic allocation (i.e. non-deterministic available storage space) and in the worst case provides additional attack vectors, e.g. with heap overflows or use-after-free. In many cases, it is just better to GC-allocate an entire growable pool or slaps of objects for fast use-case specific allocation. So whatfor I would like to use an iterator? An iterator basically is a meta-data structure which stores meta data (like indices and pointers) for accessing another data structure's contents. And if I just want to change the access of or iteration over a data structure then I don't need to touch how the actual data or memory is stored and I don't even require expensive memory allocation when I could rearrange the iterator contents inplace and if the meta data is much smaller than the actual data. All that is not achieved by `array()`. `array()` is not an iterator but a dynamically allocated copy. Using an iterator like `array[]` saves me expensive GC-allocations. When I only want to access a data structure but not mofify it then GC-allocation would not fit the lifetime logic of a variable. When I understand correctly then the iterator concept in D is called "range". Ranges neither designate a data structure nor a specific data arrangement but it defines a generic access interface of aggregate data whose purpose is to work independent of whatever data structure is accessed via this interface. Now, I'm only missing methods to allocate range iterators on the stack or modifying iterators inplace.
May 29
parent Elmar <chrehme gmx.de> writes:
On Saturday, 29 May 2021 at 19:55:30 UTC, Elmar wrote:
 In many or most of the cases the use case doesn't actually 
 require GC-allocation.
Btw, I'm talking about core-level and systems software which concentrates on data transformations.
 When I only want to access a data structure but not mofify it 
 then GC-allocation would not fit the lifetime logic of a 
 variable.
With "modification" I mean the data's size or it's order in memory but not the stored data itself.
May 29
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Wednesday, 26 May 2021 at 13:58:56 UTC, Elmar wrote:
 This example will not compile:

 ```
 	auto starts = arr[0..$].stride(2);
 	auto ends = arr[1..$].stride(2);
 	randomNumbers[] = ends[] - starts[];
 ```

 Because `[]` is not defined for the Result range. Is there a 
 standard wrapper function which wraps an elementwise `[]` 
 operator implementation around a range?
Something like this ought to work: ```d import std.range: zip; import std.algorithm: map, copy; /// calls `fun` with the members of a struct or tuple as arguments alias apply(alias fun) = args => fun(args.tupleof); zip(starts, ends) .map!(apply!((start, end) => end - start)) .copy(randomNumbers[]); ``` In general, array operators like `[]` only work with arrays. The Result ranges you get from `stride` are not arrays, so to work with them, you need to use range algorithms like the ones in `std.range` and `std.algorithm`. (Some ranges actually do support `[]`, but it is never guaranteed. You can check for such support with [`std.range.primitives.hasSlicing`][1].) If you would prefer a more convenient syntax for working with things like strided arrays, I recommend giving [libmir][2] a look. It's a high-quality collection of D libraries for numerical and scientific computing. [1]: https://phobos.dpldocs.info/std.range.primitives.hasSlicing.html [2]: https://www.libmir.org/
May 26
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, December 7, 2018 8:46:11 PM MST Adam D. Ruppe via Digitalmars-d-
learn wrote:
 On Saturday, 8 December 2018 at 03:37:56 UTC, Murilo wrote:
 Hi guys, I have created an array of strings with "string[12] ps
string[12] isn't a range, but string[] is. Try passing `ps[]` to the function instead of plain `ps` and see what happens.
Specifically, the problem is that static arrays have a fixed length, which means that you can't pop elements off as is required for ranges. Dynamic arrays on the other hand are ranges (at least as long as you import std.range.primitives to get the range functions for dynamic arrays). Slicing a static array gives you a dynamic array which is a slice of the static array. So, mutating the elements of the dynamic array will mutate the elements of the static array, but the dynamic array can have elements popped off as is required for ranges, whereas the static array can't. - Jonathan M Davis
Dec 07 2018