Thread overview
Removing entries from AAs
Aug 19, 2011
useo6
Aug 19, 2011
Timon Gehr
Aug 19, 2011
useo6
August 19, 2011
Hi,

I've create a little example of my problem:

module example;

class ExampleClass {

	public {

		int mi;

		this(int i) {
			mi = i;
		}

	}

}

int main(string[] args) {

	ExampleClass[hash_t] exp;

	ExampleClass cex = new ExampleClass(1);
	exp[cex.toHash()] = cex;

	cex = new ExampleClass(2);
	exp[cex.toHash()] = cex;

	cex = new ExampleClass(3);
	exp[cex.toHash()] = cex;

	foreach (ExampleClass c; exp) {
		if (c.mi == 2) {exp.remove(c.toHash()); }
	}

	return 0;

}

When I run this small example-app, I get an "Access Violation". When I insert a break into my foreach-loop like:

	foreach (ExampleClass c; exp) {
		if (c.mi == 2) {exp.remove(c.toHash()); break; }
	}

it works, but this means, I leave the foreach-loop. What I'm doing wrong by using the foreach-block?

Thanks for any help!
August 19, 2011
On 08/19/2011 02:01 PM, useo6 wrote:
> Hi,
>
> I've create a little example of my problem:
>
> module example;
>
> class ExampleClass {
>
> 	public {
>
> 		int mi;
>
> 		this(int i) {
> 			mi = i;
> 		}
>
> 	}
>
> }
>
> int main(string[] args) {
>
> 	ExampleClass[hash_t] exp;
>
> 	ExampleClass cex = new ExampleClass(1);
> 	exp[cex.toHash()] = cex;
>
> 	cex = new ExampleClass(2);
> 	exp[cex.toHash()] = cex;
>
> 	cex = new ExampleClass(3);
> 	exp[cex.toHash()] = cex;
>
> 	foreach (ExampleClass c; exp) {
> 		if (c.mi == 2) {exp.remove(c.toHash()); }
> 	}
>
> 	return 0;
>
> }
>
> When I run this small example-app, I get an "Access Violation". When
> I insert a break into my foreach-loop like:
>
> 	foreach (ExampleClass c; exp) {
> 		if (c.mi == 2) {exp.remove(c.toHash()); break; }
> 	}
>
> it works, but this means, I leave the foreach-loop. What I'm doing
> wrong by using the foreach-block?
>
> Thanks for any help!

The problem is that you change the AA while iterating over it. You could eg iterate over it and save all keys you want to remove into an array and then iterate over the array to remove the keys from the AA.

This works:


module example;

class ExampleClass {

	public {

		int mi;

		this(int i) {
			mi = i;
		}

	}

}

int main(string[] args) {

	ExampleClass[hash_t] exp;

	ExampleClass cex = new ExampleClass(1);
	exp[cex.toHash()] = cex;

	cex = new ExampleClass(2);
	exp[cex.toHash()] = cex;

	cex = new ExampleClass(3);
	exp[cex.toHash()] = cex;

	hash_t[] toRemove;
	
	foreach (c; exp) {
		if (c.mi == 2) { toRemove~=c.toHash(); }
	}
	foreach (h; toRemove) {
		exp.remove(h);
	}

	return 0;

}



August 19, 2011
== Auszug aus Timon Gehr (timon.gehr@gmx.ch)'s Artikel
> On 08/19/2011 02:01 PM, useo6 wrote:
> > Hi,
> >
> > I've create a little example of my problem:
> >
> > module example;
> >
> > class ExampleClass {
> >
> > 	public {
> >
> > 		int mi;
> >
> > 		this(int i) {
> > 			mi = i;
> > 		}
> >
> > 	}
> >
> > }
> >
> > int main(string[] args) {
> >
> > 	ExampleClass[hash_t] exp;
> >
> > 	ExampleClass cex = new ExampleClass(1);
> > 	exp[cex.toHash()] = cex;
> >
> > 	cex = new ExampleClass(2);
> > 	exp[cex.toHash()] = cex;
> >
> > 	cex = new ExampleClass(3);
> > 	exp[cex.toHash()] = cex;
> >
> > 	foreach (ExampleClass c; exp) {
> > 		if (c.mi == 2) {exp.remove(c.toHash()); }
> > 	}
> >
> > 	return 0;
> >
> > }
> >
> > When I run this small example-app, I get an "Access Violation".
When
> > I insert a break into my foreach-loop like:
> >
> > 	foreach (ExampleClass c; exp) {
> > 		if (c.mi == 2) {exp.remove(c.toHash()); break; }
> > 	}
> >
> > it works, but this means, I leave the foreach-loop. What I'm doing wrong by using the foreach-block?
> >
> > Thanks for any help!
> The problem is that you change the AA while iterating over it. You
could
> eg iterate over it and save all keys you want to remove into an
array
> and then iterate over the array to remove the keys from the AA.
> This works:
> module example;
> class ExampleClass {
> 	public {
> 		int mi;
> 		this(int i) {
> 			mi = i;
> 		}
> 	}
> }
> int main(string[] args) {
> 	ExampleClass[hash_t] exp;
> 	ExampleClass cex = new ExampleClass(1);
> 	exp[cex.toHash()] = cex;
> 	cex = new ExampleClass(2);
> 	exp[cex.toHash()] = cex;
> 	cex = new ExampleClass(3);
> 	exp[cex.toHash()] = cex;
> 	hash_t[] toRemove;
> 	foreach (c; exp) {
> 		if (c.mi == 2) { toRemove~=c.toHash(); }
> 	}
> 	foreach (h; toRemove) {
> 		exp.remove(h);
> 	}
> 	return 0;
> }

I already thought about that situation, but some explained the removing/clearing of an array by iterate over each element and remove it from the AA. I just solved the problem by using the HashSet-class from the dcollection's.
August 19, 2011
On Fri, 19 Aug 2011 08:28:59 -0400, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 08/19/2011 02:01 PM, useo6 wrote:
>> Hi,
>>
>> I've create a little example of my problem:
>>
>> module example;
>>
>> class ExampleClass {
>>
>> 	public {
>>
>> 		int mi;
>>
>> 		this(int i) {
>> 			mi = i;
>> 		}
>>
>> 	}
>>
>> }
>>
>> int main(string[] args) {
>>
>> 	ExampleClass[hash_t] exp;
>>
>> 	ExampleClass cex = new ExampleClass(1);
>> 	exp[cex.toHash()] = cex;
>>
>> 	cex = new ExampleClass(2);
>> 	exp[cex.toHash()] = cex;
>>
>> 	cex = new ExampleClass(3);
>> 	exp[cex.toHash()] = cex;
>>
>> 	foreach (ExampleClass c; exp) {
>> 		if (c.mi == 2) {exp.remove(c.toHash()); }
>> 	}
>>
>> 	return 0;
>>
>> }
>>
>> When I run this small example-app, I get an "Access Violation". When
>> I insert a break into my foreach-loop like:
>>
>> 	foreach (ExampleClass c; exp) {
>> 		if (c.mi == 2) {exp.remove(c.toHash()); break; }
>> 	}
>>
>> it works, but this means, I leave the foreach-loop. What I'm doing
>> wrong by using the foreach-block?
>>
>> Thanks for any help!
>
> The problem is that you change the AA while iterating over it. You could eg iterate over it and save all keys you want to remove into an array and then iterate over the array to remove the keys from the AA.
>

Note that dcollections http://www.dsource.org/project/dcollections supports removal of the currently iterated element during iteration.

See here:

http://www.dsource.org/projects/dcollections/browser/branches/d2/concepts.txt#L81

Sorry for the lack of D2 documentation, I really need to give some TLC to dcollections...

-Steve