reverse foreach

This forum is meant for questions and discussions about the X# language and tools
User avatar
wriedmann
Posts: 3763
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

reverse foreach

Post by wriedmann »

Hi,

would it possible to have a foreach that works in a reverse sense, i.e. from the last element to the first one?

I have to remove entries from a Dictionary object, and the following code gives a runtime error:

Code: Select all

foreach oItem as KeyValuePair<string,int> in oDict
  if oItem:Value == nValue
    oDict:Remove( oItem:Key )
  endif
next
As solution, I'm using this code:

Code: Select all

oRemove := List<string>{}
foreach oItem as KeyValuePair<string,int> in oDict
  if oItem:Value == nValue
    oRemove:Add( oItem:Key )
  endif
next
foreach cKey as string in oRemove
  oDict:Remove( cKey )
next
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
Phil Hepburn
Posts: 743
Joined: Sun Sep 11, 2016 2:16 pm

reverse foreach

Post by Phil Hepburn »

Hi Wolfgang,

I thought it was "forward and read only" - the enumerator !

But then what do I know.

Removal will have to be by object and not index value - for obvious reasons.

However, since you have collection(s) then why not use LINQ to create the new list to be used, and work from there !?

my 2 cents worth of the top of my head - yes, having a better day at this end, will post soon about my recent stupidity with EF6 ;-0)

Regards,
Phil.
User avatar
wriedmann
Posts: 3763
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

reverse foreach

Post by wriedmann »

Hi Phil,

I need that in my ServiceContainer class: when a tab/window is closed, it should remove all registered services from the ServiceContainer object. Therefore I need to search for value and not for key.

And using LinQ for such a thing seems to be a little bit too much....

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
NickFriend
Posts: 248
Joined: Fri Oct 14, 2016 7:09 am

reverse foreach

Post by NickFriend »

Hi Wolfgang,

LINQ could make it neater, something like (I started to put in X# syntax then realised I'd almost certainly get it wrong)....

Code: Select all

oDict = oDict.Where(d => d.Value != nValue).ToDictionary();
Nick
User avatar
wriedmann
Posts: 3763
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

reverse foreach

Post by wriedmann »

Hi Nick,

it is not an overkill when I rebuild a complete dictionary with a lot of entries only to remove some of them?

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
NickFriend
Posts: 248
Joined: Fri Oct 14, 2016 7:09 am

reverse foreach

Post by NickFriend »

Hi Wolfgang,

How big is this dictionary?.... unless it's got tens of thousands of entries I can't imagine it having the slightest impact on performance. I would expect the performance of this to be much better than looping through mulitple lists/dictionaries. Also you eliminate the Remove calls, which are probably the slowest part (I haven't got any evidence for that statement!).

I use this sort of thing all over the place without any issues at all, even in class properties to feed data into grid cells.

Nick
User avatar
wriedmann
Posts: 3763
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

reverse foreach

Post by wriedmann »

Hi Nick,

I have absolutely no idea how big this dictionary can be.

It is the central service locator in my application....

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
robert
Posts: 4534
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

reverse foreach

Post by robert »

Wolfgang,

An answer from StackExchange:

Code: Select all

var itemsToRemove = myDic.Where(f => f.Value == 42).ToArray();
foreach (var item in itemsToRemove)
    myDic.Remove(item.Key);

or

Code: Select all

foreach (var item in myDic.ToList())
{
    if (item.value == 42)
    myDic.remove(item.key);
}
Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
User avatar
wriedmann
Posts: 3763
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

reverse foreach

Post by wriedmann »

Hi Robert,

thank you. I like the second better. And I don't know what LinQ creates under the hood, so maybe the second one is faster too.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
Phil Hepburn
Posts: 743
Joined: Sun Sep 11, 2016 2:16 pm

reverse foreach

Post by Phil Hepburn »

Hi Wolfgang and all,

Contrary to what 'common myth' has to say (and the guys down the 'pub'), LINQ is just a standard part of current .NET coding.  

Nothing special is required, and the namespaces are already included by default in the standard templates for Projects.

Nick and Robert have pointed you at some LINQ based solutions to your problem, some more eloquent than others (even if they do contain Lambda clauses). Robert's first one looks a bit neater and nicer, and is almost what Nick suggested. 

We should be reaching for LINQ for all collection based processing - that's what it was designed for - COLLECTIONS.

Miss it out, and you are missing a BIG 'trick'.

RULE '1' - change and adapt !

HTH,
Phil.
Post Reply