For natural sorting in my application I currently P/Invoke a function called StrCmpLogicalW in shlwapi.dll. I was thinking about trying to run my application under Mono, but then of course I can't have this P/Invoke stuff (as far as I know anyways).
Is it possible to see the implementation of that method somewhere, or is there a good, clean and efficient C# snippet which does the same thing?
My code currently looks like this:
[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern int StrCmpLogicalW(string psz1, string psz2);
}
public class NaturalStringComparer : IComparer<string>
{
private readonly int modifier = 1;
public NaturalStringComparer() : this(false) {}
public NaturalStringComparer(bool descending)
{
if (descending) modifier = -1;
}
public int Compare(string a, string b)
{
return SafeNativeMethods.StrCmpLogicalW(a ?? "", b ?? "") * modifier;
}
}
So, what I'm looking for is an alternative to the above class which doesn't use an extern function.
I just implemented natural string comparison in C#, perhaps someone might find it useful:
public class NaturalComparer : IComparer<string>
{
public int Compare(string x, string y)
{
if (x == null && y == null) return 0;
if (x == null) return -1;
if (y == null) return 1;
int lx = x.Length, ly = y.Length;
for (int mx = 0, my = 0; mx < lx && my < ly; mx++, my++)
{
if (char.IsDigit(x[mx]) && char.IsDigit(y[my]))
{
long vx = 0, vy = 0;
for (; mx < lx && char.IsDigit(x[mx]); mx++)
vx = vx * 10 + x[mx] - '0';
for (; my < ly && char.IsDigit(y[my]); my++)
vy = vy * 10 + y[my] - '0';
if (vx != vy)
return vx > vy ? 1 : -1;
}
if (mx < lx && my < ly && x[mx] != y[my])
return x[mx] > y[my] ? 1 : -1;
}
return lx - ly;
}
}
http://www.interact-sw.co.uk/iangblog/2007/12/13/natural-sorting seems to be what you're looking for.
(and no, there is no managed equivalent to StrCmpLogicalW built into .NET)
I used regular expression to remove special characters. then casting to int. then i compared integers.
input :
List input = new List{ "6.04","6.01","6.03","6#04" };
Expected Output:
6.01
6.03
6.04
6#04
var output = input.OrderBy(s => s, new NaturalStringComparer());
foreach (var sort in output)
{
Console.WriteLine(sort);
}
public struct NaturalStringComparer : IComparer
{
public int Compare(string x, string y)
{
if (x == null && y == null) return 0;
if (x == null) return -1;
if (y == null) return 1;
int lx = x.Length, ly = y.Length;
int a = int.Parse(System.Text.RegularExpressions.Regex.Replace(x, #"\D+", ""));
int b = int.Parse(System.Text.RegularExpressions.Regex.Replace(y, #"\D+", ""));
return a.CompareTo(b);
}
}
If you're running on Windows XP or newer, you can PInvoke to the shell function StrCmpLogicalW:
public static int StrCmpLogical(String s1, String s2)
{
if (String.IsNullOrEmpty(s1) && !String.IsNullOrEmpty(s2))
return 1; //empty s1 comes after s2
else if (String.IsNullOrEmpty(s2) && !String.IsNullOrEmpty(s1))
return -1; //non-empty string comes before empty
return SafeNativeMethods.StrCmpLogicalW(s1, s2);
}
And then the internal unsafe class:
/// <summary>
/// This class suppresses stack walks for unmanaged code permission.
/// (System.Security.SuppressUnmanagedCodeSecurityAttribute is applied to this class.)
/// This class is for methods that are safe for anyone to call.
/// Callers of these methods are not required to perform a full security review to make sure that the
/// usage is secure because the methods are harmless for any caller.
/// </summary>
[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
internal static extern Int32 StrCmpLogicalW(string psz1, string psz2);
}
Related
I want to change the sorting of strings so it is based off the following alphabet:
A,E,I,O,U,F,G,L,M,N,P,S,T,V,H,K,R
Instead of the standard A,B,C,D ... X,Y,Z
So I started to try and create a IComparer but stuck on how to implement.
Here is what I got so far which ain't much.
public class CustomSort : IComparer<string>
{
public int Compare(string a, string b)
{
return 1;
}
}
Any help would be much appreciated.
It should be something very like this:
In the end you compare character by character, finding the "index" of the character inside a Order string. Perhaps to speed it up you could convert the Order string to a Dictionary<char, int> where the int is the "weight".
public class CustomSort : IComparer<string>
{
public const string Order = "AEIOUFGLMNPSTVHKR";
public int Compare(string a, string b)
{
if (a == null)
{
return b == null ? 0 : -1;
}
if (b == null)
{
return 1;
}
int minLength = Math.Min(a.Length, b.Length);
for (int i = 0; i < minLength; i++)
{
int i1 = Order.IndexOf(a[i]);
int i2 = Order.IndexOf(b[i]);
if (i1 == -1)
{
throw new Exception(a);
}
if (i2 == -1)
{
throw new Exception(b);
}
int cmp = i1.CompareTo(i2);
if (cmp != 0)
{
return cmp;
}
}
return a.Length.CompareTo(b.Length);
}
}
I'm trying to sort an ArrayList of strings (not in int).
Given:
f.e.
[0] 23,24
[1] 12,33
[2] 37,11
Arraylist.Sort should give back (sorted by the last number ascending):
[0] 37,11
[1] 23,24
[2] 12,33
Having this so far:
public class Point
{
public int i, j;
public Point(int i, int j)
{this.i = i; this.j = j;}
public string ToString()
{return i + "," + j;}
}
public class SList
{
public static void Main()
{
ArrayList Slist = new ArrayList();
Random Generate = new Random();
for (int i = 0; i < 3; i++)
{
Point p = new Point(Generate.Next(40), Generate.Next(40));
Slist.Add(p.ToString());
}
Slist.Sort();
}
}
I'm not 100% sure if you have an array of strings or if they are split already, but you can create a custom comparer and do something like this perhaps. Make clearer what you want so that people can help you better.
public class MyCustomComparer : IComparer<string>
{
public int Compare(string x, string y)
{
var xIntValues = x.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
var yIntValues = y.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
for(var i = 0; i < Math.Min(xIntValues.Count(), yIntValues.Count()); ++i)
if (xIntValues[i] != yIntValues[i])
return xIntValues[i] - yIntValues[i];
return xIntValues.Count() - yIntValues.Count();
}
}
Then use it like this where your array elements contain strings like "37, 11"
Array.Sort(myArray, MyCustomComparer);
Sort of odd to be using an ArrayList after c# 1.0, but if you have one for legacy reasons, you can create your own non-generic custom comparer, like so:
public class CustomComparer : IComparer<string>, IComparer {
#region IComparer<string> Members
int? ExtractNumber(string str)
{
int index = str.LastIndexOf(',');
if (index < 0)
return null;
var subStr = str.Substring(index+1);
int result;
if (int.TryParse(subStr, out result))
return result;
return null;
}
// Return x - y
public int Compare(string x, string y)
{
#if false
Given: f.e.
[0] 23,24
[1] 12,33
[2] 37,11
Arraylist.Sort should give back (sorted by the last number ascending):
[0] 37,11
[1] 23,24
[2] 12,33
#endif
var xVal = ExtractNumber(x);
var yVal = ExtractNumber(y);
if (!xVal.HasValue && !yVal.HasValue)
return x.CompareTo(y);
else if (!xVal.HasValue)
return 1;
else if (!yVal.HasValue)
return -1;
int cmp = xVal.Value.CompareTo(yVal.Value);
if (cmp != 0)
return cmp;
return x.CompareTo(y);
}
#endregion
#region IComparer Members
public int Compare(object x, object y)
{
if (object.ReferenceEquals(x, y))
return 0;
string xStr = x as string;
string yStr = y as string;
if (xStr == null && yStr == null)
return 0; // NO IDEA
else if (xStr == null)
return 1;
else if (yStr == null)
return -1;
else return Compare(xStr, yStr);
}
#endregion
}
The following code implements IComparable on your class. It sorts on y in ascending order:
public class Point : IComparable<Point>
{
public int x;
public int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public string ToString()
{
return x + "," + y;
}
public int CompareTo(Point other)
{
return this.y.CompareTo(other.y);
}
}
You can now use ArrayList.Sort() to achieve the order you need.
The easiest way to do this would be by stepping away from your non-generic list:
var sortedList = list.Cast<string>().OrderBy(x => x.Split(',')[1]);
The code is self-explanatory.
Using this as input:
var list = new ArrayList();
list.Add("23,24");
list.Add("12,33");
list.Add("37,11");
Yields this as output:
37,11
23,24
12,33
I have a huge array that contains reference type elements, and I want to create a lot of other arrays that essentially just point to specific parts of that one big array.
In other words, I want to create "indexers" or "pointers with lengths".
In C++ it's easy to do so using pointers and for each pointer assign a length, for example create a struct which contains a pointer with a length.
How can I achieve this in C#/.NET?
The whole point is to avoid copying anything, I just want pointers to specific parts in an array that already exists in memory.
Any ideas?
Jon's suggestion of using ArraySegment<T> is likely what you want. If however you are wanting to represent a pointer to the interior of an array, the way you can in C++, here's some code for that. No warranty is expressed or implied, use at your own risk.
This code does not track the "length" of the interior pointer in any way, but it is quite easy to add that feature if you want.
internal struct ArrayPtr<T>
{
public static ArrayPtr<T> Null { get { return default(ArrayPtr<T>); } }
private readonly T[] source;
private readonly int index;
private ArrayPtr(ArrayPtr<T> old, int delta)
{
this.source = old.source;
this.index = old.index + delta;
Debug.Assert(index >= 0);
Debug.Assert(index == 0 || this.source != null && index < this.source.Length);
}
public ArrayPtr(T[] source)
{
this.source = source;
index = 0;
}
public bool IsNull()
{
return this.source == null;
}
public static bool operator <(ArrayPtr<T> a, ArrayPtr<T> b)
{
Debug.Assert(Object.ReferenceEquals(a.source, b.source));
return a.index < b.index;
}
public static bool operator >(ArrayPtr<T> a, ArrayPtr<T> b)
{
Debug.Assert(Object.ReferenceEquals(a.source, b.source));
return a.index > b.index;
}
public static bool operator <=(ArrayPtr<T> a, ArrayPtr<T> b)
{
Debug.Assert(Object.ReferenceEquals(a.source, b.source));
return a.index <= b.index;
}
public static bool operator >=(ArrayPtr<T> a, ArrayPtr<T> b)
{
Debug.Assert(Object.ReferenceEquals(a.source, b.source));
return a.index >= b.index;
}
public static int operator -(ArrayPtr<T> a, ArrayPtr<T> b)
{
Debug.Assert(Object.ReferenceEquals(a.source, b.source));
return a.index - b.index;
}
public static ArrayPtr<T> operator +(ArrayPtr<T> a, int count)
{
return new ArrayPtr<T>(a, +count);
}
public static ArrayPtr<T> operator -(ArrayPtr<T> a, int count)
{
return new ArrayPtr<T>(a, -count);
}
public static ArrayPtr<T> operator ++(ArrayPtr<T> a)
{
return a + 1;
}
public static ArrayPtr<T> operator --(ArrayPtr<T> a)
{
return a - 1;
}
public static implicit operator ArrayPtr<T>(T[] x)
{
return new ArrayPtr<T>(x);
}
public static bool operator ==(ArrayPtr<T> x, ArrayPtr<T> y)
{
return x.source == y.source && x.index == y.index;
}
public static bool operator !=(ArrayPtr<T> x, ArrayPtr<T> y)
{
return !(x == y);
}
public override bool Equals(object x)
{
if (x == null) return this.source == null;
var ptr = x as ArrayPtr<T>?;
if (!ptr.HasValue) return false;
return this == ptr.Value;
}
public override int GetHashCode()
{
unchecked
{
int hash = this.source == null ? 0 : this.source.GetHashCode();
return hash + this.index;
}
}
public T this[int index]
{
get { return source[index + this.index]; }
set { source[index + this.index] = value; }
}
}
Now we can do stuff like:
double[] arr = new double[10];
var p0 = (ArrayPtr<double>)arr;
var p5 = p0 + 5;
p5[0] = 123.4; // sets arr[5] to 123.4
var p7 = p0 + 7;
int diff = p7 - p5; // 2
It sounds like you're looking for something like ArraySegment<T>. Contrary to my earlier thoughts, it does have an indexer and implement IEnumerable<T> etc - it's just done with explicit interfaces.
Sample code:
using System;
using System.Collections.Generic;
static class Test
{
static void Main()
{
string[] original = { "The", "quick", "brown", "fox", "jumped", "over",
"the", "lazy", "dog" };
IList<string> segment = new ArraySegment<string>(original, 3, 4);
Console.WriteLine(segment[2]); // over
foreach (var word in segment)
{
Console.WriteLine(word); // fox jumped over the
}
}
}
EDIT: As noted in comments, ArraySegment<T> is only really "fully functional" in .NET 4.5. The .NET 4 version doesn't implement any interfaces.
You could use LINQ:
yourArray.Skip(startIndex).Take(numberToTake)
The query is lazily evaluated.
For natural sorting in my application I currently P/Invoke a function called StrCmpLogicalW in shlwapi.dll. I was thinking about trying to run my application under Mono, but then of course I can't have this P/Invoke stuff (as far as I know anyways).
Is it possible to see the implementation of that method somewhere, or is there a good, clean and efficient C# snippet which does the same thing?
My code currently looks like this:
[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern int StrCmpLogicalW(string psz1, string psz2);
}
public class NaturalStringComparer : IComparer<string>
{
private readonly int modifier = 1;
public NaturalStringComparer() : this(false) {}
public NaturalStringComparer(bool descending)
{
if (descending) modifier = -1;
}
public int Compare(string a, string b)
{
return SafeNativeMethods.StrCmpLogicalW(a ?? "", b ?? "") * modifier;
}
}
So, what I'm looking for is an alternative to the above class which doesn't use an extern function.
I just implemented natural string comparison in C#, perhaps someone might find it useful:
public class NaturalComparer : IComparer<string>
{
public int Compare(string x, string y)
{
if (x == null && y == null) return 0;
if (x == null) return -1;
if (y == null) return 1;
int lx = x.Length, ly = y.Length;
for (int mx = 0, my = 0; mx < lx && my < ly; mx++, my++)
{
if (char.IsDigit(x[mx]) && char.IsDigit(y[my]))
{
long vx = 0, vy = 0;
for (; mx < lx && char.IsDigit(x[mx]); mx++)
vx = vx * 10 + x[mx] - '0';
for (; my < ly && char.IsDigit(y[my]); my++)
vy = vy * 10 + y[my] - '0';
if (vx != vy)
return vx > vy ? 1 : -1;
}
if (mx < lx && my < ly && x[mx] != y[my])
return x[mx] > y[my] ? 1 : -1;
}
return lx - ly;
}
}
http://www.interact-sw.co.uk/iangblog/2007/12/13/natural-sorting seems to be what you're looking for.
(and no, there is no managed equivalent to StrCmpLogicalW built into .NET)
I used regular expression to remove special characters. then casting to int. then i compared integers.
input :
List input = new List{ "6.04","6.01","6.03","6#04" };
Expected Output:
6.01
6.03
6.04
6#04
var output = input.OrderBy(s => s, new NaturalStringComparer());
foreach (var sort in output)
{
Console.WriteLine(sort);
}
public struct NaturalStringComparer : IComparer
{
public int Compare(string x, string y)
{
if (x == null && y == null) return 0;
if (x == null) return -1;
if (y == null) return 1;
int lx = x.Length, ly = y.Length;
int a = int.Parse(System.Text.RegularExpressions.Regex.Replace(x, #"\D+", ""));
int b = int.Parse(System.Text.RegularExpressions.Regex.Replace(y, #"\D+", ""));
return a.CompareTo(b);
}
}
If you're running on Windows XP or newer, you can PInvoke to the shell function StrCmpLogicalW:
public static int StrCmpLogical(String s1, String s2)
{
if (String.IsNullOrEmpty(s1) && !String.IsNullOrEmpty(s2))
return 1; //empty s1 comes after s2
else if (String.IsNullOrEmpty(s2) && !String.IsNullOrEmpty(s1))
return -1; //non-empty string comes before empty
return SafeNativeMethods.StrCmpLogicalW(s1, s2);
}
And then the internal unsafe class:
/// <summary>
/// This class suppresses stack walks for unmanaged code permission.
/// (System.Security.SuppressUnmanagedCodeSecurityAttribute is applied to this class.)
/// This class is for methods that are safe for anyone to call.
/// Callers of these methods are not required to perform a full security review to make sure that the
/// usage is secure because the methods are harmless for any caller.
/// </summary>
[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
internal static extern Int32 StrCmpLogicalW(string psz1, string psz2);
}
int uploadsID;
int pageNumber;
int x;
int y;
int w;
int h;
bool isValidUploadID = int.TryParse(context.Request.QueryString["uploadID"], out uploadsID);
bool isValidPage = int.TryParse(context.Request.QueryString["page"], out pageNumber);
bool isValidX = int.TryParse(context.Request.QueryString["x"], out x);
bool isValidY = int.TryParse(context.Request.QueryString["y"], out y);
bool isValidW = int.TryParse(context.Request.QueryString["w"], out w);
bool isValidH = int.TryParse(context.Request.QueryString["h"], out h);
if (isValidUploadID && isValidPage && isValidX && isValidY & isValidW & isValidH)
{
This is an ajax handler, checking all passed params are OK. Is this considered bad, and is there a better way to write this, or is it not that important?
Assuming you're not going to use the individual bool variables elsewhere, you could write that as:
int uploadsID, pageNumber, x, y, w, h;
if (int.TryParse(context.Request.QueryString["uploadID"], out uploadsID) &&
int.TryParse(context.Request.QueryString["page"], out pageNumber) &&
int.TryParse(context.Request.QueryString["x"], out x) &&
int.TryParse(context.Request.QueryString["y"], out y) &&
int.TryParse(context.Request.QueryString["w"], out w) &&
int.TryParse(context.Request.QueryString["h"], out h))
{
}
You may want to extract out int.TryParse(context.Request.QueryString[name], out variable into a separate method, leaving you with something like:
int uploadsID, pageNumber, x, y, w, h;
if (TryParseContextInt32("uploadID", out uploadsID) &&
TryParseContextInt32("page", out pageNumber) &&
TryParseContextInt32("x", out x) &&
TryParseContextInt32("y", out y) &&
TryParseContextInt32("w", out w) &&
TryParseContextInt32("h", out h))
{
}
Alternatively, you could encapsulate all this context data into a new type with a TryParse method, so you'd have something like:
PageDetails details;
if (PageDetails.TryParse(context.Request.QueryString))
{
// Now access details.Page, details.UploadID etc
}
That's obviously more work, but I think it would make the code cleaner.
Yes, start by factoring out your int.TryParse(etc.) into a separate function.
(Possibly over-influenced by F#)
//return a tuple (valid, value) from querystring of context, indexed with key
private Tuple<bool, int> TryGet(HttpContext context, string key)
{
int val = 0;
bool ok = int.TryParse(context.request.QueryString[key], out val);
return Tuple.New(ok, val);
}
Then:
var UploadId = TryGet(context, "uploadID");
//...
if(UploadId.Item1 && etc..)
{
//do something with UploadId.Item2;
To make things slightly clearer, you could
private class ValidValue
{
public bool Valid { get; private set; }
public int Value { get; private set; }
public ValidValue(bool valid, int value)
{
Valid = valid;
Value = value;
}
//etc., but this seems a bit too much like hard work, and you don't get
// equality for free as you would with Tuple, (if you need it)
I would probably go for a formatting like this
int uploadsID, pageNumber, x, y, h;
if (Int32.TryParse(context.Request.QueryString["uploadID"], out uploadsID)
&& Int32.TryParse(context.Request.QueryString["page"], out pageNumber)
&& Int32.TryParse(context.Request.QueryString["x"], out x)
&& Int32.TryParse(context.Request.QueryString["y"], out y)
&& Int32.TryParse(context.Request.QueryString["w"], out w)
&& Int32.TryParse(context.Request.QueryString["h"], out h))
{
...
}
but I don't see anything wrong with your approach.
One thing you can do is to replace this:
int uploadsID;
int pageNumber;
int x;
int y;
int w;
int h;
With this
int uploadsID, pageNumber, x, y, w, h;
try
{
// use Parse instead of TryParse
// all are valid, proceed
}
catch
{
// at least one is not valid
}
You could write a helper that gets rid of the ugly out passing style of TryParse, such as:
public delegate bool TryParser<T>(string text, out T result) where T : struct;
public static T? TryParse<T>(string text, TryParser<T> tryParser)
where T : struct
{
// null checks here.
T result;
return tryParser(text, out result) ? result : new T?();
}
And then (assuming you are only interested in validity):
bool isValid = new [] { "uploadID" , "page", "x", "y", "w", "h" }
.Select(q => context.Request.QueryString[q])
.All(t => TryParse<int>(t, int.TryParse).HasValue);
If you need the individual values:
var numsByKey = new [] { "uploadID" , "page", "x", "y", "w", "h" }
.ToDictionary(q => q,
q => TryParse<int>(context.Request.QueryString[q],
int.TryParse));
bool isValid = numsByKey.Values.All(n => n.HasValue);
This retains pretty much the same information as before, except the fine-grained info needs a lookup rather than a local-variable access.