Thread overview
Int within ranges
Jun 13, 2011
nrgyzer
Jun 13, 2011
bearophile
Jun 13, 2011
nrgyzer
Jun 13, 2011
nrgyzer
Jun 13, 2011
nrgyzer
Jun 13, 2011
Jonathan M Davis
June 13, 2011
Hi there,

is there any possibility to get a sliced array from another array between two ranges like:

int[uint] myArray;
myArray[10] = 1000;
myArray[20] = 2000;
myArray[30] = 3000;
myArray[40] = 4000;
myArray[50] = 5000;

int[] newArray = myArray[>= 20 .. <= 40]; // not able to do this writeln(newArray); // should print [2000, 3000, 4000]

Is there any way to do this?
June 13, 2011
On Mon, 13 Jun 2011 12:15:40 -0400, nrgyzer <nrgyzer@gmail.com> wrote:

> Hi there,
>
> is there any possibility to get a sliced array from another array
> between two ranges like:
>
> int[uint] myArray;
> myArray[10] = 1000;
> myArray[20] = 2000;
> myArray[30] = 3000;
> myArray[40] = 4000;
> myArray[50] = 5000;
>
> int[] newArray = myArray[>= 20 .. <= 40]; // not able to do this
> writeln(newArray); // should print [2000, 3000, 4000]
>
> Is there any way to do this?

import dcollections.TreeMap;

auto myArray = new TreeMap!(uint, int);

myArray[10] = 1000;
myArray[20] = 2000;
myArray[30] = 3000;
myArray[40] = 4000;
myArray[50] = 5000;

// this is a little kludgy, but necessary since you require <= 40
auto c = myArray.elemAt(40);
c.popFront();
int newArray = array(myArray[20..c]);

Note two things:

1. int[uint] is a hash, and so has no particular order.  Therefore, there is no guarantee of iteration order, or that a range of such a container (if one existed) would be properly constructed with two keys.  A TreeMap, or RedBlackTree, is sorted, and so the order is guaranteed.
2. dcollections.TreeMap is implemented with the same collection as std.container.RedBlackTree, so you could potentially do the same thing with it.  But the dcollections.TreeMap API is more polished.

-Steve
June 13, 2011
Steven Schveighoffer:

> But the dcollections.TreeMap API is more polished.

I think most people will want to use just Phobos, to avoid a dependency, even if the Phobos one is less polished...

Bye,
bearophile
June 13, 2011
On Mon, 13 Jun 2011 13:25:39 -0400, bearophile < <bearophileHUGS@lycos.com> wrote:

> Steven Schveighoffer:
>
>> But the dcollections.TreeMap API is more polished.
>
> I think most people will want to use just Phobos, to avoid a dependency, even if the Phobos one is less polished...

Sure, but it's difficult to demonstrate a possible solution without having the API for slicing present in the phobos version...

Essentially, what I'm saying is it *could* be done in Phobos, if phobos' RedBlackTree was updated to be like dcollections'.

-Steve
June 13, 2011
On 2011-06-13 09:15, nrgyzer wrote:
> Hi there,
> 
> is there any possibility to get a sliced array from another array between two ranges like:
> 
> int[uint] myArray;
> myArray[10] = 1000;
> myArray[20] = 2000;
> myArray[30] = 3000;
> myArray[40] = 4000;
> myArray[50] = 5000;
> 
> int[] newArray = myArray[>= 20 .. <= 40]; // not able to do this writeln(newArray); // should print [2000, 3000, 4000]
> 
> Is there any way to do this?

Slices take a contiguous chunk of an array. You can't skip any values. So, if you want them separate, you're going to have to put them in another container yourself.

- Jonathan M Davis
June 13, 2011
> On Mon, 13 Jun 2011 12:15:40 -0400, nrgyzer <nrgyzer@gmail.com>
wrote:
> > Hi there,
> >
> > is there any possibility to get a sliced array from another array between two ranges like:
> >
> > int[uint] myArray;
> > myArray[10] = 1000;
> > myArray[20] = 2000;
> > myArray[30] = 3000;
> > myArray[40] = 4000;
> > myArray[50] = 5000;
> >
> > int[] newArray = myArray[>= 20 .. <= 40]; // not able to do this writeln(newArray); // should print [2000, 3000, 4000]
> >
> > Is there any way to do this?
> import dcollections.TreeMap;
> auto myArray = new TreeMap!(uint, int);
> myArray[10] = 1000;
> myArray[20] = 2000;
> myArray[30] = 3000;
> myArray[40] = 4000;
> myArray[50] = 5000;
> // this is a little kludgy, but necessary since you require <= 40
> auto c = myArray.elemAt(40);
> c.popFront();
> int newArray = array(myArray[20..c]);
> Note two things:
> 1. int[uint] is a hash, and so has no particular order.  Therefore,
there
> is no guarantee of iteration order, or that a range of such a
container
> (if one existed) would be properly constructed with two keys.  A
TreeMap,
> or RedBlackTree, is sorted, and so the order is guaranteed.
> 2. dcollections.TreeMap is implemented with the same collection as
> std.container.RedBlackTree, so you could potentially do the same
thing
> with it.  But the dcollections.TreeMap API is more polished. -Steve

Exactly what I'm looking for, but how can I realize that it also gives me the elements when the key doesn't exists like:

import std.range;
import dcollections.TreeMap;

auto myArray = new TreeMap!(uint, int);

myArray[10] = 1000;
myArray[20] = 2000;
myArray[30] = 3000;
myArray[45] = 4500;
myArray[50] = 5000;

auto c = myArray.elemAt(40);
c.popFront();
int[] newArray = array(myArray[20..c]);
writeln(newArray);

This will throw an exception because element 40 doesn't exist. Is there any possibility to get the element 20 and 30 from this map?
June 13, 2011
On Mon, 13 Jun 2011 14:52:24 -0400, nrgyzer <nrgyzer@gmail.com> wrote:

>> On Mon, 13 Jun 2011 12:15:40 -0400, nrgyzer <nrgyzer@gmail.com>
> wrote:
>> > Hi there,
>> >
>> > is there any possibility to get a sliced array from another array
>> > between two ranges like:
>> >
>> > int[uint] myArray;
>> > myArray[10] = 1000;
>> > myArray[20] = 2000;
>> > myArray[30] = 3000;
>> > myArray[40] = 4000;
>> > myArray[50] = 5000;
>> >
>> > int[] newArray = myArray[>= 20 .. <= 40]; // not able to do this
>> > writeln(newArray); // should print [2000, 3000, 4000]
>> >
>> > Is there any way to do this?
>> import dcollections.TreeMap;
>> auto myArray = new TreeMap!(uint, int);
>> myArray[10] = 1000;
>> myArray[20] = 2000;
>> myArray[30] = 3000;
>> myArray[40] = 4000;
>> myArray[50] = 5000;
>> // this is a little kludgy, but necessary since you require <= 40
>> auto c = myArray.elemAt(40);
>> c.popFront();
>> int newArray = array(myArray[20..c]);
>> Note two things:
>> 1. int[uint] is a hash, and so has no particular order.  Therefore,
> there
>> is no guarantee of iteration order, or that a range of such a
> container
>> (if one existed) would be properly constructed with two keys.  A
> TreeMap,
>> or RedBlackTree, is sorted, and so the order is guaranteed.
>> 2. dcollections.TreeMap is implemented with the same collection as
>> std.container.RedBlackTree, so you could potentially do the same
> thing
>> with it.  But the dcollections.TreeMap API is more polished.
>> -Steve
>
> Exactly what I'm looking for, but how can I realize that it also
> gives me the elements when the key doesn't exists like:
>
> import std.range;
> import dcollections.TreeMap;
>
> auto myArray = new TreeMap!(uint, int);
>
> myArray[10] = 1000;
> myArray[20] = 2000;
> myArray[30] = 3000;
> myArray[45] = 4500;
> myArray[50] = 5000;
>
> auto c = myArray.elemAt(40);
> c.popFront();
> int[] newArray = array(myArray[20..c]);
> writeln(newArray);
>
> This will throw an exception because element 40 doesn't exist. Is
> there any possibility to get the element 20 and 30 from this map?

It might be useful to have elemAt return an empty range that is located at the place the element *would* be.

When this code was first written, in order to detect whether elemAt found your element, you compared it to container.end (similar to C++'s STL).  But now that cursors are tiny ranges, and have an empty property, I can use that to indicate the element wasn't exactly found.  So I can change the semantics to find the place the element *would* be.

myArray[20..41];

and it will find all elements >= 20 and < 41, regardless of whether 20 and 41 were valid elements.

Hm... can you post this as an enhancement to dcollections so it's not forgotten?

http://www.dsource.org/projects/dcollections/newticket

-Steve
June 13, 2011
> On Mon, 13 Jun 2011 14:52:24 -0400, nrgyzer <nrgyzer@gmail.com>
wrote:
> >> On Mon, 13 Jun 2011 12:15:40 -0400, nrgyzer <nrgyzer@gmail.com>
> > wrote:
> >> > Hi there,
> >> >
> >> > is there any possibility to get a sliced array from another
array
> >> > between two ranges like:
> >> >
> >> > int[uint] myArray;
> >> > myArray[10] = 1000;
> >> > myArray[20] = 2000;
> >> > myArray[30] = 3000;
> >> > myArray[40] = 4000;
> >> > myArray[50] = 5000;
> >> >
> >> > int[] newArray = myArray[>= 20 .. <= 40]; // not able to do
this
> >> > writeln(newArray); // should print [2000, 3000, 4000]
> >> >
> >> > Is there any way to do this?
> >> import dcollections.TreeMap;
> >> auto myArray = new TreeMap!(uint, int);
> >> myArray[10] = 1000;
> >> myArray[20] = 2000;
> >> myArray[30] = 3000;
> >> myArray[40] = 4000;
> >> myArray[50] = 5000;
> >> // this is a little kludgy, but necessary since you require <= 40
> >> auto c = myArray.elemAt(40);
> >> c.popFront();
> >> int newArray = array(myArray[20..c]);
> >> Note two things:
> >> 1. int[uint] is a hash, and so has no particular order.
Therefore,
> > there
> >> is no guarantee of iteration order, or that a range of such a
> > container
> >> (if one existed) would be properly constructed with two keys.  A
> > TreeMap,
> >> or RedBlackTree, is sorted, and so the order is guaranteed.
> >> 2. dcollections.TreeMap is implemented with the same collection
as
> >> std.container.RedBlackTree, so you could potentially do the same
> > thing
> >> with it.  But the dcollections.TreeMap API is more polished. -Steve
> >
> > Exactly what I'm looking for, but how can I realize that it also gives me the elements when the key doesn't exists like:
> >
> > import std.range;
> > import dcollections.TreeMap;
> >
> > auto myArray = new TreeMap!(uint, int);
> >
> > myArray[10] = 1000;
> > myArray[20] = 2000;
> > myArray[30] = 3000;
> > myArray[45] = 4500;
> > myArray[50] = 5000;
> >
> > auto c = myArray.elemAt(40);
> > c.popFront();
> > int[] newArray = array(myArray[20..c]);
> > writeln(newArray);
> >
> > This will throw an exception because element 40 doesn't exist. Is there any possibility to get the element 20 and 30 from this map?
> It might be useful to have elemAt return an empty range that is
located at
> the place the element *would* be.
> When this code was first written, in order to detect whether elemAt
found
> your element, you compared it to container.end (similar to C++'s
STL).
> But now that cursors are tiny ranges, and have an empty property, I
can
> use that to indicate the element wasn't exactly found.  So I can
change
> the semantics to find the place the element *would* be.
> myArray[20..41];
> and it will find all elements >= 20 and < 41, regardless of whether
20 and
> 41 were valid elements.
> Hm... can you post this as an enhancement to dcollections so it's
not
> forgotten? http://www.dsource.org/projects/dcollections/newticket -Steve

Thanks! I created a new ticket... by the way - is there any bug in DMD 2.053 by using my own opCmp? The following code throws me an HiddenFuncException:

private import std.stdio : writeln;

class Example {

	int pId;

	this(int id) {

		pId = id;

	}

	int opCmp(ref Example other) {

		return pId - other.pId;

	}

}

int main(string[] args) {

	Example[] exps;
	exps ~= new Example(1);
	exps ~= new Example(2);
	writeln(exps.sort);

	return 1;

}
June 13, 2011
On Mon, 13 Jun 2011 15:44:01 -0400, nrgyzer <nrgyzer@gmail.com> wrote:

>> On Mon, 13 Jun 2011 14:52:24 -0400, nrgyzer <nrgyzer@gmail.com>
> wrote:
>> >> On Mon, 13 Jun 2011 12:15:40 -0400, nrgyzer <nrgyzer@gmail.com>
>> > wrote:
>> >> > Hi there,
>> >> >
>> >> > is there any possibility to get a sliced array from another
> array
>> >> > between two ranges like:
>> >> >
>> >> > int[uint] myArray;
>> >> > myArray[10] = 1000;
>> >> > myArray[20] = 2000;
>> >> > myArray[30] = 3000;
>> >> > myArray[40] = 4000;
>> >> > myArray[50] = 5000;
>> >> >
>> >> > int[] newArray = myArray[>= 20 .. <= 40]; // not able to do
> this
>> >> > writeln(newArray); // should print [2000, 3000, 4000]
>> >> >
>> >> > Is there any way to do this?
>> >> import dcollections.TreeMap;
>> >> auto myArray = new TreeMap!(uint, int);
>> >> myArray[10] = 1000;
>> >> myArray[20] = 2000;
>> >> myArray[30] = 3000;
>> >> myArray[40] = 4000;
>> >> myArray[50] = 5000;
>> >> // this is a little kludgy, but necessary since you require <= 40
>> >> auto c = myArray.elemAt(40);
>> >> c.popFront();
>> >> int newArray = array(myArray[20..c]);
>> >> Note two things:
>> >> 1. int[uint] is a hash, and so has no particular order.
> Therefore,
>> > there
>> >> is no guarantee of iteration order, or that a range of such a
>> > container
>> >> (if one existed) would be properly constructed with two keys.  A
>> > TreeMap,
>> >> or RedBlackTree, is sorted, and so the order is guaranteed.
>> >> 2. dcollections.TreeMap is implemented with the same collection
> as
>> >> std.container.RedBlackTree, so you could potentially do the same
>> > thing
>> >> with it.  But the dcollections.TreeMap API is more polished.
>> >> -Steve
>> >
>> > Exactly what I'm looking for, but how can I realize that it also
>> > gives me the elements when the key doesn't exists like:
>> >
>> > import std.range;
>> > import dcollections.TreeMap;
>> >
>> > auto myArray = new TreeMap!(uint, int);
>> >
>> > myArray[10] = 1000;
>> > myArray[20] = 2000;
>> > myArray[30] = 3000;
>> > myArray[45] = 4500;
>> > myArray[50] = 5000;
>> >
>> > auto c = myArray.elemAt(40);
>> > c.popFront();
>> > int[] newArray = array(myArray[20..c]);
>> > writeln(newArray);
>> >
>> > This will throw an exception because element 40 doesn't exist. Is
>> > there any possibility to get the element 20 and 30 from this map?
>> It might be useful to have elemAt return an empty range that is
> located at
>> the place the element *would* be.
>> When this code was first written, in order to detect whether elemAt
> found
>> your element, you compared it to container.end (similar to C++'s
> STL).
>> But now that cursors are tiny ranges, and have an empty property, I
> can
>> use that to indicate the element wasn't exactly found.  So I can
> change
>> the semantics to find the place the element *would* be.
>> myArray[20..41];
>> and it will find all elements >= 20 and < 41, regardless of whether
> 20 and
>> 41 were valid elements.
>> Hm... can you post this as an enhancement to dcollections so it's
> not
>> forgotten?
>> http://www.dsource.org/projects/dcollections/newticket
>> -Steve
>
> Thanks! I created a new ticket... by the way - is there any bug in
> DMD 2.053 by using my own opCmp? The following code throws me an
> HiddenFuncException:
>
> private import std.stdio : writeln;
>
> class Example {
>
> 	int pId;
>
> 	this(int id) {
>
> 		pId = id;
>
> 	}
>
> 	int opCmp(ref Example other) {

The signature of this function must be

int opCmp(Object other)

Note, also, that ref is unnecessary, as all objects (i.e. class instances) are passed by reference.

-Steve
June 13, 2011
== Auszug aus Steven Schveighoffer (schveiguy@yahoo.com)'s Artikel
> On Mon, 13 Jun 2011 15:44:01 -0400, nrgyzer <nrgyzer@gmail.com>
wrote:
> >> On Mon, 13 Jun 2011 14:52:24 -0400, nrgyzer <nrgyzer@gmail.com>
> > wrote:
> >> >> On Mon, 13 Jun 2011 12:15:40 -0400, nrgyzer
<nrgyzer@gmail.com>
> >> > wrote:
> >> >> > Hi there,
> >> >> >
> >> >> > is there any possibility to get a sliced array from another
> > array
> >> >> > between two ranges like:
> >> >> >
> >> >> > int[uint] myArray;
> >> >> > myArray[10] = 1000;
> >> >> > myArray[20] = 2000;
> >> >> > myArray[30] = 3000;
> >> >> > myArray[40] = 4000;
> >> >> > myArray[50] = 5000;
> >> >> >
> >> >> > int[] newArray = myArray[>= 20 .. <= 40]; // not able to do
> > this
> >> >> > writeln(newArray); // should print [2000, 3000, 4000]
> >> >> >
> >> >> > Is there any way to do this?
> >> >> import dcollections.TreeMap;
> >> >> auto myArray = new TreeMap!(uint, int);
> >> >> myArray[10] = 1000;
> >> >> myArray[20] = 2000;
> >> >> myArray[30] = 3000;
> >> >> myArray[40] = 4000;
> >> >> myArray[50] = 5000;
> >> >> // this is a little kludgy, but necessary since you require
<= 40
> >> >> auto c = myArray.elemAt(40);
> >> >> c.popFront();
> >> >> int newArray = array(myArray[20..c]);
> >> >> Note two things:
> >> >> 1. int[uint] is a hash, and so has no particular order.
> > Therefore,
> >> > there
> >> >> is no guarantee of iteration order, or that a range of such a
> >> > container
> >> >> (if one existed) would be properly constructed with two
keys.  A
> >> > TreeMap,
> >> >> or RedBlackTree, is sorted, and so the order is guaranteed. 2. dcollections.TreeMap is implemented with the same
collection
> > as
> >> >> std.container.RedBlackTree, so you could potentially do the
same
> >> > thing
> >> >> with it.  But the dcollections.TreeMap API is more polished. -Steve
> >> >
> >> > Exactly what I'm looking for, but how can I realize that it
also
> >> > gives me the elements when the key doesn't exists like:
> >> >
> >> > import std.range;
> >> > import dcollections.TreeMap;
> >> >
> >> > auto myArray = new TreeMap!(uint, int);
> >> >
> >> > myArray[10] = 1000;
> >> > myArray[20] = 2000;
> >> > myArray[30] = 3000;
> >> > myArray[45] = 4500;
> >> > myArray[50] = 5000;
> >> >
> >> > auto c = myArray.elemAt(40);
> >> > c.popFront();
> >> > int[] newArray = array(myArray[20..c]);
> >> > writeln(newArray);
> >> >
> >> > This will throw an exception because element 40 doesn't exist.
Is
> >> > there any possibility to get the element 20 and 30 from this
map?
> >> It might be useful to have elemAt return an empty range that is
> > located at
> >> the place the element *would* be.
> >> When this code was first written, in order to detect whether
elemAt
> > found
> >> your element, you compared it to container.end (similar to C++'s
> > STL).
> >> But now that cursors are tiny ranges, and have an empty
property, I
> > can
> >> use that to indicate the element wasn't exactly found.  So I can
> > change
> >> the semantics to find the place the element *would* be.
> >> myArray[20..41];
> >> and it will find all elements >= 20 and < 41, regardless of
whether
> > 20 and
> >> 41 were valid elements.
> >> Hm... can you post this as an enhancement to dcollections so it's
> > not
> >> forgotten? http://www.dsource.org/projects/dcollections/newticket -Steve
> >
> > Thanks! I created a new ticket... by the way - is there any bug in DMD 2.053 by using my own opCmp? The following code throws me an HiddenFuncException:
> >
> > private import std.stdio : writeln;
> >
> > class Example {
> >
> > 	int pId;
> >
> > 	this(int id) {
> >
> > 		pId = id;
> >
> > 	}
> >
> > 	int opCmp(ref Example other) {
> The signature of this function must be
> int opCmp(Object other)
> Note, also, that ref is unnecessary, as all objects (i.e. class
instances)
> are passed by reference.
> -Steve

Works, thanks for all that!