|
Thank You Both For the Answers!
|
|
|
|
|
How can I have property that have something like this property:
item : (Collection)...
|
|
|
|
|
in toolstrip control we have a property name Item ,so i wanna have something like this.
|
|
|
|
|
I need a function to return the maximum font size (for a given font)such that a given
string will fit in a predefined box (rectangle).
That is, I want to use DrawString(string, font, brush, rectangle) to draw the string
in a fixed size box. Note that Drawstring will wrap the string automatically to fit
the width. I don't want any of the string to extend beyond the bottom of the box.
BTW, this for a windows application using forms.
Thanks for any suggestions!
Tom
modified on Saturday, January 30, 2010 5:50 PM
|
|
|
|
|
Hi,
there is Graphics.MeasureString() which calculates the required width (for single-line) or required height (for multi-line and given a fixed width); it works pretty well provided you give it the exact same parameters (font, style, etc) you are going to give DrawString later. So you would need a little iteration:
1. choose some rather large fontsize;
2. calculate required height;
3. reduce fontsize by available_size/required_size;
4. repeat 2+3 two or three times.
Warning: there are some minor deviations; I once saw a CP article on the very subject. The solution then is to use TextRenderer class; I never felt a need to do that though.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read code that is properly formatted, adding PRE tags is the easiest way to obtain that. [The QA section does it automatically now, I hope we soon get it on regular forums as well]
|
|
|
|
|
Hi Luc
I came across this myself a little while ago when I discovered some inaccuracies in MeasureString when I used it in a custom control.
In my particular situation it was more of an annoyance than a requirement so I decided to live with it, but if accurate measurement is required then MeasureString doesn't quite cut it.
Apparently MeasureCharacterRanges can help too (according to the notes I made at the time).
|
|
|
|
|
Thanks Dave, so there are three ways now. I still wonder why they can't do it right the first time and leave it there, it's not that MeasureString and DrawString are doing very different things...
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read code that is properly formatted, adding PRE tags is the easiest way to obtain that. [The QA section does it automatically now, I hope we soon get it on regular forums as well]
|
|
|
|
|
I agree. It's something to do with aliasing in GDI IIRC but it seems a pretty poor excuse. It should be able to calculate it's own size if DrawString were to be called.
|
|
|
|
|
That solved the problem.
Thanks!
Tom
|
|
|
|
|
I did something similar a few years ago. I found the MeasureString wasn't accurate at times and the constant measuring I was forced to do came with a steep performance penalty. I solved the problem by creating a background bitmap image, big enough to fit my text in the format I required, and at 96 point size and them drew the image to a custom control to display the text, scaled down or up to the desired size. I only needed to calculate the text size once per string needed, instead of every time I had to rescale the display.
|
|
|
|
|
0) Get the pixel width of the container box.
1) Divide the box width by the number of characters in your string. This will give you your "desired average character width.
2) Get the average character width of the font that you want to use, and starting at the current font size, get the average character width. Depending on whether the average character width is less than or greater than the desired character width, loop up or down in font size until you find one that matches, or is a little smaller.
3) Once you get to a candidate font size, measure the width of your string using that font, and see if it fits. If it doesn't bump the font size up or down as appropriate.
.45 ACP - because shooting twice is just silly ----- "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001
|
|
|
|
|
I have a large file that I wish to sort. By large, I mean the file is sufficiently large such that
it will not fit into RAM. I would like to do this by writing a C# program. I am wondering if C# has an external sort method. Can I use LINQ?
Thanks
Bob
|
|
|
|
|
Hi Bob,
BobInNJ wrote: an external sort method
None that I know of.
BobInNJ wrote: Can I use LINQ?
That wouldn't help solving the size problem, and not improve performance.
I'm not sure what your data types are, what fraction of each item you need in order to sort it, nor your sorting criteria.
In general, I see two valid approaches:
1.
stuff it all in a database, sort and export.
You could do that interactively or write an app to do it.
2.
Or write a little app that reads part of the data (say 100MB), sorts it and sends it to a temporary file.
repeat N times till all data processed.
then perform a merge-sort of those N files to 1 final result file.
PS: it often is wise to avoid large files all together; if you can't hold it in memory, it will be trouble sooner or later. Do you really need it all in one file? e.g. if an app generates a lot of log info, just start a new file every so often.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read code that is properly formatted, adding PRE tags is the easiest way to obtain that. [The QA section does it automatically now, I hope we soon get it on regular forums as well]
|
|
|
|
|
Luc,
Thanks for the response. The fields in the file are all numbers. The key is a floating point number. I am thinking that stuffing it into a database, sorting and then exporting it is going to be a lot of work. Also, I do not have a database system (such as MS Sql Server) loaded on my machine. Therefore, I think I am going with your second suggestion. I also think your PS comment is very good.
Bob
|
|
|
|
|
Bob,
my very first part of the reply wasn't very accurate. You could:
- create a small class (MyItem) that represents an item from your file;
- fill a List<MyItem> with all items (even when the data itself remains in the file);
- provide an IComparer that knows how to compare two such objects;
- then use List.Sort(IComparer) ;
- and finally generate a new file based on the new sort order.
more on this can be found in here[^].
BTW: I'm not saying this is easier than the split and merge approach I suggested earlier.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read code that is properly formatted, adding PRE tags is the easiest way to obtain that. [The QA section does it automatically now, I hope we soon get it on regular forums as well]
|
|
|
|
|
FYI, you do not need an IComparer. There is an overload of List.Sort that takes a delegate (and hence a lambda).
|
|
|
|
|
Thanks for the reminder. I have now updated my article.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read code that is properly formatted, adding PRE tags is the easiest way to obtain that. [The QA section does it automatically now, I hope we soon get it on regular forums as well]
|
|
|
|
|
Too bad the key is a "floating point number" (ugly and not too practical for sorting).
If it was a character key or if you can convert the float, you can use the "SORT" command from the command line / command prompt.
|
|
|
|
|
That reminds me. I did something similar here a few years ago. As I recall, it was in response to a "Friday Programming Quiz".
The file was rows (CSV) of CP members with member ID first. The task was to devise the smallest sort method.
1,...
10,...
100,...
2,...
etc.
My solution was to pipe the file through a program that left-padded the IDs to (perhaps) six places, then piped the output through SORT.
That sort (snicker) of technique may work for the OP as well.
Edit: Whoops, nope, different situation[^].
modified on Saturday, January 30, 2010 11:31 PM
|
|
|
|
|
Since you did not specify, I assumed that your file was some sort of CSV where each line is a row and the key field is the first piece in the line. If not, the idea should be enough to get you started. If you can hold the keys all in memory along with the other record keeping data, you could do it this way. Otherwise, you will need to do a Luc suggested in the first reply and split into smaller files, sort the smaller, and merge.
This is how I would implement Luc's last suggestion:
IEnumerable<string> fileEnumer = System.IO.File.ReadAllLines("input.txt");
var rows = (from line in fileEnumer
select new LineInfo(float.Parse(line.Split(',')[0]), line.Length))
.ToList();
long curPos = 0;
foreach (var lineInfo in rows)
{
lineInfo.LineStart = curPos;
curPos += lineInfo.LineLength;
}
rows.Sort((left, right) => left.Id.CompareTo(right.Id));
using (var inStream = new System.IO.FileStream("input.txt",
System.IO.FileMode.Open,
System.IO.FileAccess.Read,
System.IO.FileShare.None))
{
using (var reader = new System.IO.StreamReader(inStream))
{
using (var output = new System.IO.StreamWriter("output.txt"))
{
foreach (var lineInfo in rows)
{
inStream.Seek(lineInfo.LineStart, System.IO.SeekOrigin.Begin);
output.WriteLine(reader.ReadLine());
}
}
}
}
public class LineInfo
{
public LineInfo(float id, int lineLength)
{
this.Id = id;
this.LineLength = lineLength;
}
public float Id { get; private set; }
public int LineLength { get; private set; }
public long LineStart { get; set; }
}
EDIT: After further review, if you made a SelectWithPrevious extension method, you could make everything above the copying portion a bit more LINQish and lose the LineInfo class. Note that there is of course no error handling anywhere in any of this code.
public static IEnumerable<TResult>
SelectWithPrevious<TSource, TResult>(this IEnumerable<TSource> source,
Func<TSource, TResult, TResult> selector,
TResult firstPrevious)
{
foreach (var item in source)
{
firstPrevious = selector(item, firstPrevious);
yield return firstPrevious;
}
}
IEnumerable<string> fileEnumer = null; ;
var rows = from row in fileEnumer
.SelectWithPrevious((line, previous) => new {Id = float.Parse(line.Split(',')[0]),
LineLength = line.Length,
LineStart = previous.LineStart + previous.LineLength},
new {Id = 0.0F, LineLength = 0, LineStart = 0})
orderby row.Id
select row;
modified on Sunday, January 31, 2010 1:02 PM
|
|
|
|
|
Gideon Engelberth wrote: This is how I would implement Luc's last suggestion
you're very kind, however
Gideon Engelberth wrote: System.IO.File.ReadAllLines("input.txt");
is not what I would do when dealing with a problem whose description started with "I have a large file that ...". We do not really want all data in memory at once, so an explicit ReadLine() loop seems more adequate.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read code that is properly formatted, adding PRE tags is the easiest way to obtain that. [The QA section does it automatically now, I hope we soon get it on regular forums as well]
|
|
|
|
|
Gideon Engelberth wrote: //Read the file in and get just the key field along with
//some tracking information to find the line later.
//Getting the lines one at a time instead of all at once like ReadAllLines
//is an exercise left to the reader.
IEnumerable<string> fileEnumer = System.IO.File.ReadAllLines("input.txt");
I did mention that you would have to do something else. I suppose I should have left that as a /* do stuff here */ instead of typing ReadAllLines.
|
|
|
|
|
Sorry, seems I ignored some comments and went straight to the code.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read code that is properly formatted, adding PRE tags is the easiest way to obtain that. [The QA section does it automatically now, I hope we soon get it on regular forums as well]
|
|
|
|
|
BobInNJ wrote: Also, I do not have a database system
look at sqlite - Im sure there's a C# interface for it somewhere - I use it all the time (from c++) for sorting/grouping large amounts of data
'g'
|
|
|
|
|
I would like to thank the group for there responses. The responses were quite educational for me as I am still learning C#.
I plan to solve the problem by using the sort command that comes with the package cygwin. As it turns out, the key is always in the range of 0 to 1 so I can treat it as a string.
Bob
|
|
|
|
|