|
Let's assume that you are storing the data in a class that stores the properties as X and Y values. It's easy enough to sort the data using LINQ, first by ORDERBY on the X and then the Y. Do this in a single query.
|
|
|
|
|
Why sort it at all? You can plot unsorted values. :shrug:
On the other hand, part of what I was playing with over the last few days involved X,Y,value objects and I keep them in a Dictionary<int,object> (like a sparse* matrix, and the int Key is essentially a hash of the X and Y -- (X<<16)|Y ). In my case, I then use nested for loops to access the content of the Dictionary in the order I want them.
for ( y = miny ; y <= maxy ; y++ )
for ( x = minx ; x <= maxx ; x++ )
if ( data.ContainsKey ( hash ( x , y ) ) ...
This requires that I update the min and max x and y as I add items to the dictionary, but that's no big deal.
* There may be only 10% or fewer active items over the two-dimensional address space.
modified 29-Dec-14 17:03pm.
|
|
|
|
|
I've written this type of Class so many times I think I could write it half-asleep
using System.Collections.Generic;
using System.Linq;
namespace YetAnother
{
public class PointyPoint
{
public int X { set; get; }
public int Y { set; get; }
public double Value { set; get; }
public PointyPoint() {}
public PointyPoint(int x, int y, double value)
{
X = x;
Y = y;
Value = value;
}
}
public enum PointySortType
{
PSortAscendingX,
PSortAscendingY,
PSortDescendingX,
PSortDescendingY,
PSortAscendingValue,
PSortDescendingValue
}
public class PointyListClass : List<PointyPoint>
{
public PointyListClass() {}
public List<PointyPoint> PointySortedBy(PointySortType pSType, PointyListClass pointyList)
{
if (pointyList == null || pointyList.Count == 1) return null;
switch (pSType)
{
case PointySortType.PSortAscendingX:
{
return pointyList.OrderBy(pointy => pointy.X).ToList();
}
case PointySortType.PSortAscendingY:
{
return pointyList.OrderBy(pointy => pointy.Y).ToList();
}
case PointySortType.PSortDescendingX:
{
return pointyList.OrderByDescending(pointy => pointy.X).ToList();
}
case PointySortType.PSortDescendingY:
{
return pointyList.OrderByDescending(pointy => pointy.Y).ToList();
}
case PointySortType.PSortAscendingValue:
{
return pointyList.OrderBy(pointy => pointy.Value).ToList();
}
case PointySortType.PSortDescendingValue:
{
return pointyList.OrderByDescending(pointy => pointy.Value).ToList();
}
}
return null;
}
}
}
private void SomeButton_Click(object sender, EventArgs e)
{
PointyListClass pointyList = new PointyListClass
{
{new PointyPoint(100,400,199.99)},
{new PointyPoint(200,300,12.43)},
{new PointyPoint(300,200,-12333)},
{new PointyPoint(400,100,345.93)},
};
var pointyXAscending = pointyList.PointySortedBy(PointySortType.PSortAscendingX, pointyList).ToList();
var pointyYAscending = pointyList.PointySortedBy(PointySortType.PSortAscendingY, pointyList).ToList();
var pointyXDescending = pointyList.PointySortedBy(PointySortType.PSortDescendingX, pointyList).ToList();
var pointyDescending = pointyList.PointySortedBy(PointySortType.PSortDescendingY, pointyList).ToList();
var pointyValueAscending = pointyList.PointySortedBy(PointySortType.PSortAscendingValue, pointyList).ToList();
var pointyValueDescending = pointyList.PointySortedBy(PointySortType.PSortDescendingValue, pointyList).ToList();
}
«A man will be imprisoned in a room with a door that's unlocked and opens inwards ... as long as it does not occur to him to pull rather than push» Wittgenstein
|
|
|
|
|
Every time you use ToList or ToArray a puppy is baked into a pie.
|
|
|
|
|
Well, at least that Pie has fur on it, rather than being bald
«A man will be imprisoned in a room with a door that's unlocked and opens inwards ... as long as it does not occur to him to pull rather than push» Wittgenstein
|
|
|
|
|
Eh... like the Pie guy said, too many ToList()'s . That makes a copy of the list and enumerates the list and makes copies, etc.
But also, this is kinda overkill since the linq syntax is well known and cleaner...
OrderBy((x) => x.X)
OrderBy((x) => x.Y)
Syntactic sugar shouldn't have less sugar then the syntactic thing its attempting to sugar.
|
|
|
|
|
"That makes a copy of the list and enumerates the list and makes copies, etc."
The result of a Linq statement is not a "concrete instance" of a generic List, rather it is an internal form of what you might call the "makings of a generic List:" only when you access the Linq result by, for example, using 'foreach on its contents, or using .ToList, etc., is an actual final form "rendered."
"Syntactic sugar shouldn't have less sugar then the syntactic thing its attempting to sugar." So, let me get this straight: you object to having a method in a Class that returns the result of one of several possible sort-orders depending on the value of an Enum ?
It's a good thing I'm not your manager, because you are the kind of sledge hammer I would set to work breaking concrete, rather than writing code
«A man will be imprisoned in a room with a door that's unlocked and opens inwards ... as long as it does not occur to him to pull rather than push» Wittgenstein
|
|
|
|
|
BillWoodruff wrote: The result of a Linq statement is not a "concrete instance" of a generic List,
rather it is an internal form of what you might call the "makings of a generic
List:" only when you access the Linq result by, for example, using 'foreach on
its contents, or using .ToList, etc., is an actual final form "rendered."
Yeah, thats why we were saying you shouldn't use .ToList(). You can return an ordered enumeration of the list without "rendering" it.
BillWoodruff wrote: So, let me get this straight: you object to having a method in a Class that
returns the result of one of several possible sort-orders depending on the value
of an Enum ?
Didn't you do that for syntactic sugar purposes? To make it easier for the caller to return the list? I don't object to encapsulating functionality, I object to doing it in an unknown / custom way when there is a well known, standard way to do it . Just my opinion though. YMMV. As I mentioned, OrderBy(x => x.Y) to me seems easier / shorter then your enum method.
Also, I (perhaps mistakenly?) assumed you implemented that sort functionality in the class itself for use in a UI? Or is it for internal application use? I haven't run across any project yet where the sort order is not either hard-coded in a specific order for internal application use or the sort order is influenced by the user through the UI. Again, just my personal experience. If you have an internal need to sort data differently in different situations, I'd love to hear the use case out of curiousity.
If you did do it for use in a UI, Microsoft already has an established pattern in .Net for filtering and/or sort collections and that ain't it . The pattern doesn't specifically have to be used for UI work, but as I said, its extremely rare to have to sort in different ways unless the user requests it. See ICollectionView.
BillWoodruff wrote: It's a good thing I'm not your manager, because you are the kind of sledge
hammer I would set to work breaking concrete, rather than writing code
All my code tends to follow well known, established and accepted patterns . I'm kind of a stickler for that.
|
|
|
|
|
Here's a challenge for you, Mighty Hammer: write a response to the OP here that demonstrates what you consider "best practices"
It's rather clear to me reading your responses that you do not understand Linq fully, and grasp that no "copy" is made of the whatever structure that is processed by a Linq query.
I think you also miss the Zen humor in Piebald's comment: to bake a puppy into a pie is, indeed, to transform it, and a Linq query result is a transformed, often filtered so one has a pointer to a subset of all possible objects; it's kind of a "map" to what will be finally rendered as a result of the transformation.
What I am surprised that neither you, nor Piebald, pointed out is that all of the Linq queries shown in this example act on all of the objects in the set: no filtering here; and it is correct that Linq queries that sort, and use of operators like Cast, will always have more potential overhead than Linq queries that use Linq operators, for example 'Where, that do filter.
I don't find your comments about "standard techniques" credible, which doesn't mean I don't believe that you have evolved a set of practices that are quite useful in the kind of code you write in the context of your work, and which you now believe are "standard." We all generalize from our experience in ways that both enable, and limit, us.
Code I write in response to questions on CP is written with the goal of educating the OP, and I try to make it as "general" as possible, to communicate its intent as clearly as possible. In writing this code I felt the example just might be more useful, in the long run, on CP, if I demonstrated using an Enum, using a Switch/Case, providing an example of a utility class with a gamut of useful options (the various sorts).
Some wise words by Jon Skeet concerning the "overhead" of Linq queries: [^].
«A man will be imprisoned in a room with a door that's unlocked and opens inwards ... as long as it does not occur to him to pull rather than push» Wittgenstein
|
|
|
|
|
Sadly, it is you who does not understand LINQ fully. Allow me to impart some wisdom on you with my mighty hammer .
List<int> lst = new List<int>();
lst.Add(1);
lst.Add(2);
lst.Add(3);
System.Diagnostics.Debug.WriteLine(lst[1]);
var v1 = lst.OrderBy(x => x);
var v2 = lst.ToList();
lst[1] = 7;
foreach (int i in lst)
System.Diagnostics.Debug.WriteLine("L: " + i);
foreach (int i in v1)
System.Diagnostics.Debug.WriteLine("V1: " + i);
foreach (int i in v2)
System.Diagnostics.Debug.WriteLine("V2: " + i);
Output:
2
L: 1
L: 7
L: 3
V1: 1
V1: 3
V1: 7
V2: 1
V2: 2
V2: 3
You'll notice that the original list has become 1,7,3 (the L). V1 has become 1,3,7 because its the same list (and sorting is lazy). Now notice V2... OMG... its still 1,2,3!!!
Crazy, huh?
ToList() and ToArray() are special in LINQ. They make a COPY of the list. However, it is a SHALLOW copy. Since ints, floats, doubles, etc. are VALUE types, you get a brand new copy of them.
With REFERENCE types, you'll still get a BRAND NEW list with references to the original objects. HOWEVER, if you add / remove from the original list, the add / delete will not be propagated because its a different list.
If you didn't do the ToList(), it would work the way you expect with reference types too.
With that being said, most other LINQ operations are lazy. However, ToList() and ToArray() are NOT.
Thank you. Please play again .
|
|
|
|
|
Gosh, of course Value types are copied: that's the definition of what a Value type is.
Please see my comments to Piebald here: [^].
In your example: when you call 'ToList on 'v2 which is not a Linq intermediary structure, but a "real live" instance of a List, you are not performing an act which is any way equivalent to what Linq does. I note that I would never, in "real world" code, expect to see a call to 'ToList on something that is already in "final form."
Yet, while you are performing reductio ad absurdum in this swing of the mighty mallet, and miss the target by a country mile, I still so cherish the way you swing that hammer
Happy New Year
cheers, Bil
«A man will be imprisoned in a room with a door that's unlocked and opens inwards ... as long as it does not occur to him to pull rather than push» Wittgenstein
|
|
|
|
|
Sorry Bill, but it seems you are indulging in the festivities of the new year a tad early.
*You* claimed ToList() does not create a new list when it in fact does. Value types will of course be copied and reference types will of course be referenced. However, it is not the instance of the list that you think it is. Thus you will run into situations like I have shown you as well as others.
While my example trivially used lst.ToList() for simplicity, if you got off your condescending high horse for a second, you'd realize that LINQ operations operate on IEnumerable sequences. Of which ListT is one. However, IEnumerableT is not a ListT.
Since I'm sure you'll retort with one of your childish condescending replys, I'll leave you with this C&P from MSDN:
The ToList<tsource>(IEnumerable<tsource>) method forces immediate query evaluation and returns a List<t> that contains the query results. You can append this method to your query in order to obtain a cached copy of the query results.
ToArray<tsource> has similar behavior but returns an array instead of a List<t>.
Drop the cocky attitude kid, you might learn something.
Bye .
|
|
|
|
|
BillWoodruff wrote: The result of a Linq statement is not a "concrete instance" of a generic List
Correct; it's an IEnumerable.
BillWoodruff wrote: by, for example, using 'foreach
No; that's not a problem.
BillWoodruff wrote: or using .ToList
Exactly. That's what you're doing. ToList is making a concrete copy -- your library code should not being using ToList; it should just be returning the IEnumerable, the same as the Linq methods do. If the final output should be a List or Array or whatever, that should be done as late as possible, by the application, not by library routines that don't know how the output will be used.
|
|
|
|
|
Happy New Year, Piebald !
I am a fan of late-binding as late as possible, so I'm in step with you on that point. And, as I commented to Mighty Hammer, the code I write here is meant to be "educational;" it's not the same code I might write were I part of a team of other programmers, all of whom were using some library class I wrote: in that scenario I might well have the method return only the Linq structure, not return the "instantiated" List.
Where I believe I diverge in opinion re the result of a Linq query after its evaluation/rendering into "final form" requires a distinction between a Linq query that returns a bunch-of/sequence-of Values rather than References.
So I'd argue that a Linq query that returns a bunch of selected/filtered pointers to Class instances rendered into a generic List of said Classes: does not make a copy in the sense of a "deep copy;" rather, it just wraps a bunch of pointers to said instances in a List.
However, a Linq query rendered to a List that returns a set of integers, or strings: yeah, them are copies.
Does this clarify anything ?
cheers, Bill
«A man will be imprisoned in a room with a door that's unlocked and opens inwards ... as long as it does not occur to him to pull rather than push» Wittgenstein
|
|
|
|
|
Not really. Did you forget that structures are value types too? And thus you'll get a copy of them? Oh hey... look at that, Point is actually a structure and not a class. So is Rect and various other things that people usually treat as classes when they are actually structures.
EDIT: BTW, yes, I realized in your example Point is inside of a class which is a bit different.
|
|
|
|
|
Your abilities for off-topic ramblings are truly impressive. My reply to PieBald mentioned nothing about .NET objects like Structs; and I am very aware of the .NET objects which are Structs, Point, Rect, etc., and the fact that Structs are internally handled as a Value Type.
I specifically talked about instances of Classes as an example of how a Linq query will create a wrapper around a set of references-to instances, not copies-of instances, for certain Object Types.
I hope this is just a phase you are going through
«A man will be imprisoned in a room with a door that's unlocked and opens inwards ... as long as it does not occur to him to pull rather than push» Wittgenstein
|
|
|
|
|
BillWoodruff wrote: the code I write here is meant to be "educational;"
Then please don't lead newbies down the rabbit hole of bad Linq -- show them only the One True Path because they will think your code is "best practice".
BillWoodruff wrote: does not make a copy in the sense of a "deep copy;"
It's still a needless copy; it's still very bad, and newbies won't know the difference.
Furthermore, if your method is generic, unless it specifies a struct constraint), it won't know whether the data is value-type or not. In practice, it's not a worthwhile distinction; don't make any needless copies of anything.
Furthermore, consider some collection and a chain of n Linq/Lambda filters, each of which returns a List rather than a simple enumerator. You've copied the each datum (values or references I don't care) n times.
With the same n tasks performed with only one ToList at the end, you copy each datum only once.
-- The foregoing is likely over-simplified and not strictly true, because the enumerators involved also copy the data one-by-one as it passes through, so perhaps there are 2n copies "your way" and n+1 copies "my way".
Another thing I want to point out is that the final task might be "take 10" (or similar) which means "my way" only iterates and copies those 10 data, not all of them -- whereas calling ToList at intermediate steps will cause a lot of needless intermediate copying.
|
|
|
|
|
I think you are generalizing from speculating about advanced use-case scenarios to some unwarranted conclusions about potential confusion for beginners in understanding how Linq operates.
Yes, there is confusion about Linq operates, and, yes, beginners to using Linq do get confused trying to form a "mental model" of its internal dynamic operation which is useful. And, certain Linq concepts and operators like "Yield return," and the use of 'New are ... imho ... just difficult to "get down."
I find it significant that one of the most popular books on Linq (Albahari's) is one of the worst technical books I've ever seen; however, Albahari's LinqPad tool is a great resource.
The specific example I gave here may have given you an occasion to vent your spleen, and enjoy spouting off the typical kind of blanket put-down that often characterizes your responses here on CodeProject, but, I consider that "your curmudgeonly thing," and, honestly, I'm not really disturbed by it; I find it entertaining on one level. Perhaps because I get into "curmudgeonly" myself !
However, I don't want to let the hot volcanic mud you discharge out your deep-sea smoking fumarole confuse other people.
Anyone who thinks they know the "one true path" to, or from, anywhere, is ... truly ... lost
Happy New Year ! Bill
«A man will be imprisoned in a room with a door that's unlocked and opens inwards ... as long as it does not occur to him to pull rather than push» Wittgenstein
|
|
|
|
|
Message Closed
modified 29-Dec-14 11:11am.
|
|
|
|
|
Hi all, I am pretty new to coding, and am attempting to port this code from C to c#, and cannot figure out the createfile section. Do i need it? can i replace it with something?
original C.
HANDLE openAndSetupComPort(const TCHAR* comport)
{
HANDLE com_handle;
DCB dcb_serial_params = { 0 };
COMMTIMEOUTS timeouts = { 0 };
DWORD com_error;
COMSTAT comstat;
com_handle = CreateFile(comport,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (com_handle == INVALID_HANDLE_VALUE){
printf("Error opening port\n");
return INVALID_HANDLE_VALUE;
}
dcb_serial_params.DCBlength = sizeof(dcb_serial_params);
if (!GetCommState(com_handle, &dcb_serial_params)){
printf("Failed to get the previous state of the serial port\n");
CloseHandle(com_handle);
return INVALID_HANDLE_VALUE;
}
dcb_serial_params.BaudRate = 115200;
dcb_serial_params.ByteSize = 8;
dcb_serial_params.StopBits = ONESTOPBIT;
dcb_serial_params.Parity = NOPARITY;
if (!SetCommState(com_handle, &dcb_serial_params)){
printf("Failed to set the serial port's state\n");
}
timeouts.ReadIntervalTimeout = -1;
timeouts.ReadTotalTimeoutConstant = 100;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 100;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(com_handle, &timeouts)){
printf("Failed to set the timeouts\n");
CloseHandle(com_handle);
return INVALID_HANDLE_VALUE;
}
Sleep(300);
ClearCommError(com_handle, &com_error, &comstat);
if (comstat.cbInQue != 0){
PurgeComm(com_handle, PURGE_RXCLEAR | PURGE_TXCLEAR);
}
return com_handle;
}
which is being called here:
if(!WriteFile(com_handle, write_bytes, sizeof(write_bytes), &bytes_written, 0)){
printf("Error writing to port\n");
return 2;
}
So I am opening a serial port:
public static void SerialSetupIMU()
{
_serialPort = new SerialPort();
_serialPort.PortName = "COM11";
_serialPort.BaudRate = 115200;
_serialPort.Parity = Parity.None;
_serialPort.DataBits = 8;
_serialPort.StopBits = StopBits.One;
_serialPort.Handshake = Handshake.None;
_serialPort.ReadTimeout = 100;
_serialPort.WriteTimeout = 100;
_serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);
try
{
_serialPort.Open();
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
}
catch
{
Console.Write("port does not exist");
}
if (_serialPort.IsOpen)
Console.Write("port 11 opened");
}
and attempting to write:
_serialPort.Write(com_handle , write_bytes, byteSize, bytes_written, 0);
And it fails on the 'com_handle', obviously, because I haven't added it. But what is it expecting there?
Any help would be much appreciated!
Thank you much.
|
|
|
|
|
C# is an object oriented language, C isn't.
When you create and open the SerialPort object it "remembers" which port handle it should use internally, so you don't need to think about it - you just tell the SerialPort instance to write, and it sorts it all out for you: http://msdn.microsoft.com/en-us/library/ms143551(v=vs.110).aspx[^]
So, once you have the port opened, just write your data to it:
_serialPort.Write(write_bytes, 0, write_bytes.Length); Will write all the bytes in the write_bytes array to the port.
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Thanks for your answer!
_serialPort.Write(write_bytes, 0, write_bytes.Length);
is giving me a
'no overload for method takes 3 arguments' exception.
|
|
|
|
|
actually, my bad. that is working great. thanks again!
|
|
|
|
|
You're welcome!
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Hi,
Regarding sqlConnection, is it recommended to keep it open all across the application or open it every time I want to use it then close it? Which method is better for the memory?
Thanks,
Jassim
Technology News @ www.JassimRahma.com
|
|
|
|
|