fbpx
Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1
  • 2

TOPIC: reverse foreach

reverse foreach 2 years 5 months ago #813

  wriedmann's Avatar Topic Author wriedmann Offline Posts: 1545
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:
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:
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
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Last edit: by wriedmann.

reverse foreach 2 years 5 months ago #814

  Phil Hepburn's Avatar Phil Hepburn Offline Posts: 742
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.

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #815

  wriedmann's Avatar Topic Author wriedmann Offline Posts: 1545
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
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #816

  NickFriend's Avatar NickFriend Offline Posts: 184
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)....
oDict = oDict.Where(d => d.Value != nValue).ToDictionary();

Nick

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #817

  wriedmann's Avatar Topic Author wriedmann Offline Posts: 1545
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
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #818

  NickFriend's Avatar NickFriend Offline Posts: 184
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

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #819

  wriedmann's Avatar Topic Author wriedmann Offline Posts: 1545
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
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #821

  robert's Avatar robert Offline Posts: 969
Wolfgang,

An answer from StackExchange:
var itemsToRemove = myDic.Where(f => f.Value == 42).ToArray();
foreach (var item in itemsToRemove)
    myDic.Remove(item.Key);


or
foreach (var item in myDic.ToList())
{
    if (item.value == 42)
    myDic.remove(item.key);
}

Robert
XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

Last edit: by robert.

reverse foreach 2 years 5 months ago #822

  wriedmann's Avatar Topic Author wriedmann Offline Posts: 1545
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
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #823

  Phil Hepburn's Avatar Phil Hepburn Offline Posts: 742
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.

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #824

  wriedmann's Avatar Topic Author wriedmann Offline Posts: 1545
Hi Robert,

the second one does not work:
'Dictionary<string, int>' does not contain a definition for 'ToList' and no extension method 'ToList' accepting a first argument of type 'Dictionary<string, int>' could be found

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

Last edit: by wriedmann.

reverse foreach 2 years 5 months ago #825

  wriedmann's Avatar Topic Author wriedmann Offline Posts: 1545
Hi Phil,

the LinQ code does not work either:
var oItems := oDict:Where( {|Item| Item:Value == nValue } )
foreach var oItem in oItems
  oDict:Remove( oItem:Key )
next

gives a runtime error because the enumeration was changed and operations cannot be executed anymore (translated from my German error message).

Wolfgang

P.S. sometimes I have the bad feeling that I'm simply not intelligent enough for all these new things
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #826

  Chris's Avatar Chris Offline Posts: 1137
Hi Wolfgang,

That's because ToList() is an extension method, defined in the System.Linq.Enumerable class of System.Core.dll. For this reason, you must make sure you have a reference to System.Core and also include a USING System.Linq in your prg file.

Chris
XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #827

  wriedmann's Avatar Topic Author wriedmann Offline Posts: 1545
Hi Robert,

I'm very sorry, the second sample works:
foreach var oItem in oDict:ToList()
  if oItem:Value == nValue
    oDict:Remove( oItem:Key )
  endif
next

after adding System.Core and System.Linq to the references and adding a few using statements.

Sorry again!

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #828

  Phil Hepburn's Avatar Phil Hepburn Offline Posts: 742
See Wolfgang,

We don't need to be clever, or intelligent - what we all need is the will to keep going ;-0)

Persevere, that is the clue ! keep on trying !!

Yesterday, and a couple of days previous to that, I had some bad 'give up' moments believe me ;-0((

Now things are working again, and life is sweet.

At least you always know that you will get good support and help from your xBase friends and colleagues. I would know nothing without their support over the years.

Thanks to all of you.

Now then ... Good Luck,
and have a nice weekend.
Seasonal greetings to one and all.
Phil.
 

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #829

  Phil Hepburn's Avatar Phil Hepburn Offline Posts: 742
Hi guys,

Surely we can leave out the removal stuff altogether ?

After my Tea (hot meal) I will try some code similar to this below :-

var oRequiredItems := oDict:Where( {|Item| Item:Value !== nValue } )

oDict := oRequiredItems

Above we select the items we need, not the ones we don't. Since we already have our new collection then all we need do is a new assignment.

Or have I missed something ?

Best regards to all,
Phil.

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #830

  NickFriend's Avatar NickFriend Offline Posts: 184
I don't know why I bothered doing this, but anyway....

Dictionary with 1 million items, every other one is removed.

Method 1 = 00:00:00.1022951 (Wolfgang's original)
Method 2 = 00:00:00.0773887 (Robert's second)
Method 3 = 00:00:00.1158190 (mine)

In other words it doesn't make the slightest difference to speed (we're talking a million items here) which technique you use.

Your choice, 9 lines of code or 1.

Nick

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #831

  Frank Maraite's Avatar Frank Maraite Offline Posts: 172
Wolfgang, Nick, Phil, Chris and Robert,

thanks for this nice session! Learned a lot.

BTW: MSDN says, that Add() is an O(1) and remove is a nearly O(1) operation. This may be the reason for no time differences.

Frank

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #832

  wriedmann's Avatar Topic Author wriedmann Offline Posts: 1545
Hi all,

my part of this thread was very modest...

But for Nick: unfortunately I'm not able to move your code to X#, and the MS documentation says that there is not ToDictionary() method without any parameters - the X# compiler says the same thing.
I have tried this code:
oDict := oDict:Where( {|Item| Item:Value != nValue } ):ToDictionary()

As I understand, the code should be
oDict := oDict:ToDictionary( {|Item| Item:Value != nValue } )

but it gives the error
error XS0029: Cannot implicitly convert type 'System.Collections.Generic.Dictionary<logic, System.Collections.Generic.KeyValuePair<string, int>>' to 'System.Collections.Generic.Dictionary<string, int>'

Will keep trying....

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
This email address is being protected from spambots. You need JavaScript enabled to view it.
www.riedmann.it - docs.xsharp.it

Please Log in or Create an account to join the conversation.

reverse foreach 2 years 5 months ago #834

  Frank Maraite's Avatar Frank Maraite Offline Posts: 172
Wolfgang,

I know nothing about LINQ, but found ( msdn.microsoft.com/de-de/library/bb549277(v=vs.110).aspx )

ToDictionary(p => p.TrackingNumber)

so try
ToDictionary(p => p:Value)
Frank

Please Log in or Create an account to join the conversation.

  • Page:
  • 1
  • 2