reverse foreach

This forum is meant for questions and discussions about the X# language and tools
NickFriend
Posts: 248
Joined: Fri Oct 14, 2016 7:09 am

reverse foreach

Post by NickFriend »

Wolfgang,

Google and StackOverflow are your friends....

Code: Select all

dict = dict.Where(d => d.Value != nValue).ToDictionary(t => t.Key, t=> t.Value);
Nick
User avatar
robert
Posts: 4518
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

reverse foreach

Post by robert »

Nick,
Thanks fo the benchmak.

If you present it like this, with all the leading zeros, then the difference looks very small
Presented like this the difference is more obvious:

102 milliseconds (W)
77 milliseconds (R)
115 milliseconds (N)

It is clear that the R is ~ 40% faster.
On this scale it may seem like a little bit, but if you use the correct algorithms everywhere in your code and benchmark them, like you just did, then the result will be software that runs faster.

If you ever wondered why X# is so much faster than Vulcan, this is exactly why.
And of course we build on top of the code base of some geniuses from Microsoft.

Robert
Nick Friend wrote: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
XSharp Development Team
The Netherlands
robert@xsharp.eu
NickFriend
Posts: 248
Joined: Fri Oct 14, 2016 7:09 am

reverse foreach

Post by NickFriend »

Hi Robert,

Yes and no! In the context of a compiler, you're 100% correct I'm sure, but here we're talking about a business type application (I assume).

In this case, 99.99% of the application time is spent doing absolutely nothing while the user stares at the screen (or videos of cats on Youtube). So in this case IMHO there are two much more important factors - ease of use for the end-user, and clear easily maintainable code for the developer, as long as the performance is within reasonable bounds.

I did the benchmarks with exaggerated quantities of items to make the point that all these styles of operation are phenomenally fast compared with the speed of a user! I did various tests, and the results vary dramatically with the quantity of data processed. For example if you drop it down to say 1000 items instead of 1 million, Wolfgang's original code is way faster (presumably because there's a certain overhead in the LINQ queries).

But the point is it just doesn't matter in this sort of application, so for me the conclusion is that you can safely use whichever style of programming you feel most comfortable with without worrying about performance. In the context of a compiler or other situation where small performance gains really are critical, then yes, you have to watch what you're doing very carefully.

Nick
User avatar
Phil Hepburn
Posts: 743
Joined: Sun Sep 11, 2016 2:16 pm

reverse foreach

Post by Phil Hepburn »

Hi Nick, Robert, W, F and all,

Nick I totally agree with your sentiments and reasoning.

However, I do think we need to get used to the LINQ syntax as it is not going to go away, AND, there are places that we will have no choice but use it. It IS very powerful and elegant once we get our heads around it.  Which is years for you and me remember.

Like you I did not know why I got into messing with code (attached here) but got a nice one liner to do the task in one go - and two filter clauses as well, one on Key and the other on Value - NICE !

I like the Microsoft preferred LINQ query syntax when it is possible to replace Lambda. Again it is easier to maintain and understand than enumerator loops and stuff.

Oh! - by the way THANKS - you solve my issue I went to bed with and now I know how to apply the 'ToDictionary()' extended method. It works just fine.

Here are three small images of a full test code in X# so others could do similar if they wish.
Dictionary_11.jpg
Dictionary_11.jpg (106.49 KiB) Viewed 486 times
 
Dictionary_12.jpg
Dictionary_12.jpg (118.16 KiB) Viewed 486 times
 
Dictionary_13.jpg
Dictionary_13.jpg (108.71 KiB) Viewed 486 times
My big issue yesterday (as always for me) was getting the results of my LINQ query into the correct 'Type' - the resulting collection Type I mean.

Now it works fine with your Googling details.

If I had been able to use intellisense I may have been able to see the requirements for this overload. Still, not bad for working blind ;-0)

Cheers to all,
and yes, I have learned a lot too.
P.S. I will try and send the code - BUT - remember the LINQ namespace requirements as well!
Fingers crossed .........

Code: Select all

	
local implied oDict := Dictionary<string, string>{}
//--- key, value ---
oDict:Add("txt", "notepad.exe")
oDict:Add("bmp", "paint.exe")
oDict:Add("dib", "paint.exe")
oDict:Add("rtf", "wordpad.exe")
oDict:Add("ybmp", "ypaint.exe")
oDict:Add("zdib", "zpaint.exe")
oDict:Add("artf", "awordpad.exe")
oDict:Add("btxt", "bnotepad.exe")
oDict:Add("cbmp", "cpaint.exe")
oDict:Add("ddib", "dpaint.exe")
oDict:Add("ertf", "ewordpad.exe")

MessageBox.Show(oDict:GetType():ToString(),"Dict type Original :")

oDict := (from d in oDict where d:Key <> "txt"  where d:Value <> "paint.exe" select d) ;					
                                               :ToDictionary({|r| r.Key}, {|r| r.Value})
			
MessageBox.Show(oDict:GetType():ToString(),"Dict type Result :")
MessageBox.Show(oDict:Count():ToString(),"Dict count :")			
User avatar
Phil Hepburn
Posts: 743
Joined: Sun Sep 11, 2016 2:16 pm

reverse foreach

Post by Phil Hepburn »

Hi Nick and all,

Just to remind readers that this sample / exercise with a Dictionary, is a good example of what is known as 'LINQ to Objects' or 'L2O'.

The object referred to is any in-memory collection object. All LINQ syntax applies to 'L2O' as well as 'L2S' and 'L2E' - its all the same as it is applied to the collection object.

Note 'L2E' is now often called 'Entity LINQ' as opposed to the older title of 'LINQ to Entity'.

??? Presumably soon we will have a title of "Entity-Core LINQ" ??? As Entity Core seems to be the new name for 'EF7'.

Note in the Dictionary example there is no 'back-end' database being accessed.

There is quite a bit of detail on 'L2O' in my eNotes being prepared for Cologne 2017.
Dictionary_21.jpg
Dictionary_21.jpg (103.37 KiB) Viewed 486 times
Because this is such a good example, and that we now have some good working solutions, I will include it in the eNotes - I will mention your name 'Nick' ;-0)

Seasons best wishes,
Phil.
User avatar
wriedmann
Posts: 3755
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

reverse foreach

Post by wriedmann »

Hi,

to give the final solution: a one-liner in X# Syntax corresponding to Nick's C# code:

Code: Select all

oDict := oDict:Where( {|Item| Item:Value != nValue } ):ToDictionary( {|Item| Item:Key }, {|Item| Item:Value } )
Personally, my preference is Robert's second suggestion:

Code: Select all

foreach oItem as KeyValuePair<string,int> in oDict:ToList()
  if oItem:Value == nValue
    oDict:Remove( oItem:Key )
  endif
next
because it is more code, but it is faster to read and easier to understand.

Performance IS an issue even in business applications. It is true that the program most of the time is waiting for the users input, but nothing frustrates a user more than a slow program response. Therefore I try to work and look at performance every time.

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 guys,

Of cause if we are not counting lines (to say "my solution is better than your solution"!) then we get more clarity in the LINQ code when it is formatted / structured as seen in the first image :- ( this is Microsoft's query syntax - highest level of abstraction )



{ Robert there is still an issue with image attachment / inserting - am struggling a bit! ]

Now then folks - below is the Dictionary (collection) bound to a DataGrid WPF control both before and after the LINQ selection process :-
Dictionary_32.jpg
Dictionary_32.jpg (31.64 KiB) Viewed 486 times
Dictionary_33.jpg
Dictionary_33.jpg (24.08 KiB) Viewed 486 times
Four elements / entries have now disappeared.

Happy Christmas,
Phil.
User avatar
Phil Hepburn
Posts: 743
Joined: Sun Sep 11, 2016 2:16 pm

reverse foreach

Post by Phil Hepburn »

Yes, told you Robert that links and attachments are playing up - my main one (first one) somehow got missed out altogether - here is go TWO ;-0((
Dictionary_31.jpg
Dictionary_31.jpg (114.58 KiB) Viewed 486 times
Cheers,
Phil.

Thumbs held !!!
Post Reply