Peter Petrov’s Weblog

var me = from practice in programming where practice.IsBestPractice && practice.UseLambda select practice.OptimalPerformance;

Parse string having comma separated integers August 1, 2011

Filed under: .NET Framework,C# — ppetrov @ 8:01 pm
Tags: ,

I’ve read a blog post about splitting a string containing comma separated integers and then creating an array. It’s a very short and simple code but there’s a little problem – it uses the Split() method and the result is an array, potentially big array. What if you only need the first 10 results out of ten thousand integers ? You will do the work to split ten thousand integers and you will consume a lot memory then you need and finally you will create a lot of garbage. I’ve written a class to solve this issues.

public class IntConverter
{
private readonly char _separator;

public IntConverter()
: this(',')
{
}

public IntConverter(char separator)
{
_separator = separator;
}

public IEnumerable<int> From(string input)
{
if (input == null) throw new ArgumentNullException("input");

return FromImplementation(input.Trim(), _separator);
}

public string To(IEnumerable<int> numbers)
{
if (numbers == null) throw new ArgumentNullException("numbers");

var buffer = new StringBuilder();

foreach (var n in numbers)
{
if (buffer.Length > 0)
{
buffer.Append(_separator);
}
buffer.Append(n.ToString());
}

return buffer.ToString();
}

private IEnumerable<int> FromImplementation(string input, char separator)
{
if (input == string.Empty)
{
yield break;
}

var buffer = new StringBuilder();

var symbols = input.ToCharArray();
for (var i = 0; i < symbols.Length; i++)
{
var symbol = symbols[i];
var isSeparator = (symbol == separator);
if (isSeparator)
{
yield return int.Parse(buffer.ToString());
buffer.Length = 0;
}
else
{
buffer.Append(symbol);
}
}

yield return int.Parse(buffer.ToString());
}
}

I wish there will be an overload of int.Parse or int.TryParse witch accepts StringBuilder as input to reduce even more the memory usage in this scenario.

 

Useful method – 7 of N – Ignore case on String.Replace() June 27, 2008

Filed under: .NET Framework,C# — ppetrov @ 3:51 pm
Tags: , , ,

I’ve posted a method to determine if a string contains another string ignoring the case. I’ve also looked all string methods and I’ve found Replace isn’t available in a ignore case variant. I’ve created the missing overload(using an extension methods).

public static string Replace(this string original, string oldValue, string newValue, StringComparison comparisionType)
 {
 if (oldValue == null)
 throw new ArgumentNullException("oldValue");
 if (newValue == null)
 throw new ArgumentNullException("newValue");

 var result = original;

 if (oldValue != newValue)
 {
 int index = -1;
 int lastIndex = 0;

 var buffer = new StringBuilder();

 while ((index = original.IndexOf(oldValue, index + 1, comparisionType)) >= 0)
 {
 buffer.Append(original, lastIndex, index - lastIndex);
 buffer.Append(newValue);

 lastIndex = index + oldValue.Length;
 }
 buffer.Append(original, lastIndex, original.Length - lastIndex);

 result = buffer.ToString();
 }
 return result;
 }

UPDATE : I’ve updated the method to allow newValue to be string.Empty. It will perform like a remove method. WordPress source code posting is broken 😦

 

Useful method – 6 of N – Ignore case on String.Contains()

Filed under: .NET Framework,C# — ppetrov @ 12:39 pm
Tags: , , ,

The easiest way to see if a String contains another string is to use the method Contains().

The documentation has Remarks

This method performs an ordinal (case-sensitive and culture-insensitive) comparison. The search begins at the first character position of this string and continues through the last character position.

But what if we want a case-insensitive comparison? The answer is simple – we can use IndexOf(). The problem is the name of the method isn’t as intuitive as Contains() is(Contains calls IndexOf under the hood). To create a little comfort I’ve wrapped the IndexOf() call to an extension method which will determine if a string contains another string ignoring the case.

public static bool Contains(this string original, string value, StringComparison comparisionType)
{
    return original.IndexOf(value, comparisionType) >= 0;
}

In fact we pass StringComparison as parameter so it’s easy to specify the culture and the case.

 

Useful method – 5 of N – Format/Beautify XML June 24, 2008

Filed under: C#,XML — ppetrov @ 7:27 pm
Tags: , , ,

Here’s a method to format a XML string or a XML file.

    public static string Format(string xmlContents)
    {
        StringBuilder buffer = new StringBuilder();

        XmlDocument doc = new XmlDocument();
        doc.LoadXml(xmlContents);

        using (var writer = XmlTextWriter.Create(buffer, new XmlWriterSettings() { Indent = true }))
        {
            doc.Save(writer);
        }

        return buffer.ToString();
    }

    public static void FormatFile(string inputFile)
    {
        FormatFile(inputFile, inputFile);
    }

    public static void FormatFile(string inputFile, string outputFile)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(inputFile);

        using (var writer = XmlTextWriter.Create(outputFile, new XmlWriterSettings() { Indent = true }))
        {
            doc.Save(writer);
        }
    }

I’ve tried to optimize these methods by replacing the XmlDocument with XPathDocument. The documentation of XPathDocument says:

Provides a fast, read-only, in-memory representation of an XML document using the XPath data model.

My first thought was that the read-only nature of XPathDocument will speed up my code, so I end up with this method.

    public static string FormatUsingXPath(string xmlContents)
    {
        StringBuilder buffer = new StringBuilder();

        using (var writer = XmlTextWriter.Create(buffer, new XmlWriterSettings() { Indent = true }))
        {
            using (XmlTextReader reader = new XmlTextReader(xmlContents, XmlNodeType.Document, null))
            {
                XPathDocument doc = new XPathDocument(reader);
                writer.WriteNode(doc.CreateNavigator(), false);
            }
        }

        return buffer.ToString();
    }

Unfortunately the XPath version is 10% slower. I think the difference comes from the creation of the XmlTextReader.

If we apply the method on the following unformatted XML


<?xml version="1.0"?>
<catalog>
 <book id="bk101">
 <author>Gambardella, Matthew</author><title>XML Developer's Guide</title>

 <genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
 <description>An in-depth look at creating applications
 with XML.</description>

 </book>
</catalog>

we will receive a well formatted version of our input XML.

Unfortunately there’s a problem with wordpress.com XML formatting and the well formatted XML isn’t shown as expected.

 

Useful method – 4 of N – String Aggregation

Filed under: C# — ppetrov @ 1:23 pm
Tags: ,

I’ve read a blog post on extension methods. There is a method on String Aggregation but I didn’t like its implementation. A few months back, I have coded the same method. Here’s my version

        public static string Aggregate<T>(this IEnumerable<T> values)
        {
            return Aggregate(values, ",");
        }

        public static string Aggregate<T>(this IEnumerable<T> values, string separator)
        {
            return values.Aggregate(x => x.ToString(), separator);
        }

        public static string Aggregate<T>(this IEnumerable<T> values, Func<T, string> toString)
        {
            return values.Aggregate(toString, ",");
        }

        public static string Aggregate<T>(this IEnumerable<T> values, Func<T, string> toString, string separator)
        {
            if (values == null)
            {
                throw new ArgumentNullException("values");
            }
            if (toString == null)
            {
                throw new ArgumentNullException("toString");
            }

            StringBuilder buffer = new StringBuilder();

            foreach (var v in values)
            {
                if (buffer.Length > 0)
                {
                    buffer.Append(separator);
                }
                buffer.Append(toString(v));
            }

            return buffer.ToString();
        }

This version is 10 times faster and it uses less memory. The method in the post creates many temporary strings, so it consumes a lot of memory. Probably we can speed up my implementation by removing the check

if (buffer.Length > 0) { //... }

and removing the separator from the start but I don’t like the idea because it will create a copy of the resulting (big) string.

 

Useful method – 3 of N – Validate IP address June 18, 2008

Filed under: C# — ppetrov @ 7:20 pm
Tags:

If you need to know if a string is a valid IP address this utility methods can help you

public static bool IsValidIPAddress(string address)
{
return IsValidIPAddress(address, IPVersion.V4);
}

public static bool IsValidIPAddress(string address, IPVersion version)
{
bool isValid = false;

if (!string.IsNullOrEmpty(address))
{
if (address.Length <= ((int)version * 3) + 3) { var parts = address.Split('.'); if (parts.Length == (int)version) { isValid = true; int index = 0; while (isValid && index < parts.Length) { byte partValue; isValid &= byte.TryParse(parts[index++], out partValue); } } } } return isValid; } [/sourcecode]where IPVersion is the following enum [sourcecode="csharp"] public enum IPVersion { V4 = 4, V6 = 6 } [/sourcecode]

 

Useful method – 2 of N – Shuffle/Randomize Array or List June 17, 2008

Filed under: C# — ppetrov @ 11:48 am
Tags:

From time to time I need to shuffle an array or a list. Unfortunately there is no such method as Randomize() or Shuffle() defined as a static method on the System.Array class or somewhere else. So I write down these extension methods on List<T> and T[].

For the array:

public static void ShuffleInPlace<T>(this T[] values)
{
    ExtensionUtils.GenericShuffle(values);
}

public static T[] Shuffle<T>(this T[] values)
{
    if (values == null)
    {
        throw new ArgumentNullException("values");
    }
    T[] copy = new T[values.Length];
    Array.Copy(values, copy, values.Length);

    copy.ShuffleInPlace();

    return copy;
}

For the list:


public static List<T> Shuffle<T>(this List<T> values)
{
 List<T> copy = new List<T>(values);
 copy.ShuffleInPlace();
 return copy;
}

public static void ShuffleInPlace<T>(this List<T> values)
{
 ExtensionUtils.GenericShuffle(values);
}

where the class ExtensionUtils is defined like this

public static class ExtensionUtils
{
    public static void GenericShuffle<T>(IList<T> values)
    {
        if (values == null)
        {
            throw new ArgumentNullException("values");
        }
        if (values.Count > 0)
        {
            Random r = new Random();

            int position = 0;
            for (int i = values.Count - 1; i > 0; i--)
            {
                position = r.Next(i + 1);
                T temp = values[i];
                values[i] = values[position];
                values[position] = temp;
            }
        }
    }
} 

Now we can shuffle out arrays or lists very easily.