ways to improve the time of the execution - Data structures - c#

I am learning Data Structures and I am stuck in a problem I cannot find the way to improve the performance of the code. The problem is this: https://www.hackerrank.com/challenges/contacts/problem I made the solution and I could pass 3 of the 15 tests, but the rest I couldnĀ“t because show me:
Time limit exceeded Your code did not execute within the time limits.
Please optimize your code. For more information on execution time
limits, refer to the environment page
I change the nested if with linq, but I couldn't get the improvement. Could you help me? I left the code I am using:
public static List<int> contacts (List<List<string>> queries)
{
List<string> contactList = new List<string>();
List<string> findList = new List<string>();
List<int> result = new List<int>();
foreach (var instruction in queries)
{
if (instruction[0] == "add")
contactList.Add(instruction[1]);
else
findList.Add(instruction[1]);
}
for(int i = 0; i < findList.Count; i++)
{
//-----------------------------------------------------------------------
var counter = contactList.Where(x => x.Contains(findList[i])).Count();
result.Add(counter);
//-----------------------------------------------------------------------
//foreach (var contact in contactList)
//{
// if (contact.Contains(findList[i]))
// result[i]++;
//}
}
return result;
}
Thanks in advance for your help

Thanks for your advices! I made a research about the issue and I leave the solution in C#
using System.Collections.Generic;
namespace ConsoleApp2 {
internal class Program
{
static void Main(string[] args)
{
var x = contacts(new List<List<string>>() {
new List<string> {"add", "hack" },
new List<string> {"add", "hackerrank" },
new List<string> {"find", "hac" },
new List<string> {"find", "hak" }
});
}
public static List<int> contacts (List<List<string>> queries)
{
Trie trie = new Trie();
var findList = new List<int>();
foreach (var instruction in queries)
{
if (instruction[0] == "add")
trie.add(instruction[1]);
else
findList.Add(trie.find(instruction[1]));
}
return findList;
}
}
class TrieNode
{
private Dictionary<char, TrieNode> children = new Dictionary<char, TrieNode>();
public int size;
public void putChildIfAbsent(char ch)
{
if(!children.ContainsKey(ch))
children.Add(ch, new TrieNode());
}
public TrieNode getChild(char ch)
{
if (children.ContainsKey(ch))
return children[ch];
return null;
}
}
class Trie
{
TrieNode root = new TrieNode();
public void add(string str)
{
TrieNode curr = root;
foreach(char ch in str)
{
curr.putChildIfAbsent(ch);
curr=curr.getChild(ch);
curr.size++;
}
}
public int find(string prefix)
{
TrieNode curr = root;
foreach(char ch in prefix)
{
curr= curr.getChild(ch);
if (curr == null)
return 0;
}
return curr.size;
}
}
}

Related

Trie implementation: Search method with weird return value

I am fairly new to C# and working on a project in which I need to build a prefix tree (trie). Searching in the trie should return a list of words matching a given search prefix.
That's the code I have so far, but the search doesnt actually return the value I'm looking for and instead returns "Trees.PrefixTree+d__5". What am I doing wrong or what do I have to change to get it run?
Thank you very much in advance!
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
namespace Trees
{
public class Program
{
public static void Main()
{
//String[] file = File.ReadAllLines(#"C:\Users\samue\Desktop\Neuer Ordner (2)\liste.txt");
string[] dictionary = new string[] { "test", "try", "angle", "the", "code", "is", "isnt" };
PrefixTree trie = new PrefixTree();
var sw = new Stopwatch();
foreach (var word in dictionary)
{
trie.Add(word);
}
//Thread workerThread = new Thread(trie.Search(suchwort);
Console.WriteLine(trie.Search("te"));
}
}
public class PrefixTree
{
private PrefixTreeNode root;
public PrefixTree()
{
root = new PrefixTreeNode(String.Empty);
}
public void Add(string word)
{
AddRecursive(root, word, String.Empty);
}
private void AddRecursive(PrefixTreeNode node, string remainingString, string currentString)
{
if (remainingString.Length <= 0)
{
return;
}
char prefix = remainingString[0];
string substring = remainingString.Substring(1);
if (!node.SubNodes.ContainsKey(prefix))
{
node.SubNodes.Add(prefix, new PrefixTreeNode(currentString + prefix));
}
if (substring.Length == 0)
{
node.SubNodes[prefix].IsWord = true;
return;
}
else
{
AddRecursive(node.SubNodes[prefix], substring, currentString + prefix);
}
}
public IEnumerable<string> Search(string searchString)
{
PrefixTreeNode node = root;
foreach (var search in searchString)
{
if (!node.SubNodes.ContainsKey(search))
{
return new string[0];
}
node = node.SubNodes[search];
}
return FindAllWordsRecursive(node);
}
private IEnumerable<string> FindAllWordsRecursive(PrefixTreeNode node)
{
if (node.IsWord)
{
yield return node.Word;
}
foreach (var subnode in node.SubNodes)
{
foreach (var result in FindAllWordsRecursive(subnode.Value))
{
yield return result;
}
}
}
protected class PrefixTreeNode
{
private readonly Dictionary<char, PrefixTreeNode> subNodes;
private bool isWord;
private readonly string word;
public PrefixTreeNode(string word)
{
subNodes = new Dictionary<char, PrefixTreeNode>();
isWord = false;
this.word = word;
}
public Dictionary<char, PrefixTreeNode> SubNodes { get { return subNodes; } }
public bool IsWord { get { return isWord; } set { isWord = value; } }
public string Word { get { return word; } }
}
}
}
Try changing your Console.WriteLine() to this:
Console.WriteLine(string.Join(", ", trie.Search("te")));
You were not concatenating all the strings together!

C# How to add string to a list from a different file

I'm new to C# and OOP I have two different files. File A where I've created the list.
//This file will contain predetermine list of responses.
using System.Linq;
using System.Collections.Generic;
public class Responses
{
//bot name
static string nomber = "Jarvis";
List<string> answer = new List<string>(){
$"Mi nomber ta {nomber}",
"Mi ta bon"
};
public void AddToList(string value){
this.answer.Add(value);
}
public string Answer(int id)
{
return answer.ElementAt(id);
}
}
And in file B I have these two lines of code to add the string 1 to the list, I've also included the Generics and Linq System in file B.
var response = new Responses();
response.answer.Add("1");
I've tried creating a method called AddToList to pass the value and add it to the list, but with no luck. When I try to display the list at index 2 I'll get an argument out of range instead of the value "1".
*Also both files are located in the same folder.
After read your source code, I understand your problem. First you Add new element to Response.answers of Interperter and it return id then you get Response.answer of Output by that id. Of course you never get that, because they were 2 different instances.
I provide 2 options for you:
Option 1: Make Reponses single instance (singleton)
Responses.cs
using System.Linq;
using System.Collections.Generic;
public class Responses
{
private static Responses _instance = new Responses();
public static GetInstance() {
return _instance;
}
//bot name
static string nomber = "Jarvis";
List<string> answer = new List<string>(){
$"Mi nomber ta {nomber}",
"Mi ta bon"
};
public void AddToList(string value){
this.answer.Add(value);
}
public string Answer(int id)
{
return answer.ElementAt(id);
}
}
Then change on other files
//from
var responses = new Responses();
//to
var responses = Responses.GetInstance();
//from
responses.answer.Add()
//to
reponses.AddToList()
Option 2: Make Responses static
Response.cs
using System.Linq;
using System.Collections.Generic;
public static class Responses
{
//bot name
static string nomber = "Jarvis";
static List<string> answer = new List<string>(){
$"Mi nomber ta {nomber}",
"Mi ta bon"
};
public static void AddToList(string value){
this.answer.Add(value);
}
public static string Answer(int id)
{
return answer.ElementAt(id);
}
}
Output.cs
using System;
public class Output
{
public void Return(int respondType, int respond)
{
switch(respondType)
{
case 0:
Console.WriteLine(Responses.Answer(respond));
break;
default:
Console.WriteLine("Mi no ta kompronde");
break;
}
}
}
Interperter.cs
using System.Collections.Generic;
using System.Linq;
public class Interpreter
{
public int UserInputType(string value)
{
// Turns the user input into an array of words
string[] words = value.Split(' ');
int returnValue = 2;
//int match = 0;
Responses.AddToList("1");
//This stores the correct response to the given question
//var element = new List<int>();
foreach(var word in words)
{
// if(!string.IsNullOrWhiteSpace(word))
// {
foreach(var listOfQuestions in userInputedQuestions)
{
//Convert words in the listOfQuestions to array string to match them with the userInputedQuestion
string[] listOfQWords = listOfQuestions.Split(" ");
//Check how many words matches the predefined list of questions
foreach(var qWord in listOfQWords){
if(word == qWord){
returnValue = 0;
}
}
}
}
// }
return returnValue;
}
private List<string> userInputedQuestions = new List<string>(){
"Ki ta bo nomber?",
"Konta ku bo?"
};
}
Hope it helps

Read x number of lines of a file at a time C#

I want to read and process 10+ lines at a time for GB files, but haven't found a solution to spit out 10 lines until the end.
My last attempt was :
int n = 10;
foreach (var line in File.ReadLines("path")
.AsParallel().WithDegreeOfParallelism(n))
{
System.Console.WriteLine(line);
Thread.Sleep(1000);
}
I've seen solutions that use buffer sizes but I want to read in the entire row.
The Default behavour is to read all the Line in one shot, if you want to read less than that you need to dig a little deeper into how it reads them and get a StreamReader which will then let you control the reading process
using (StreamReader sr = new StreamReader(path))
{
while (sr.Peek() >= 0)
{
Console.WriteLine(sr.ReadLine());
}
}
it also has a ReadLineAsync method that will return a task
if you contain these tasks in an ConcurrentBag you can very easily keep the processing running on 10 lines at a time.
var bag =new ConCurrentBag<Task>();
using (StreamReader sr = new StreamReader(path))
{
while(sr.Peek() >=0)
{
if(bag.Count < 10)
{
Task processing = sr.ReadLineAsync().ContinueWith( (read) => {
string s = read.Result;//EDIT Removed await to reflect Scots comment
//process line
});
bag.Add(processing);
}
else
{
Task.WaitAny(bag.ToArray())
//remove competed tasks from bag
}
}
}
note this code is for guidance only not to be used as is;
if all you want is the last ten lines then you can get that with the solution here
How to read a text file reversely with iterator in C#
This method would create "pages" of lines from your file.
public static IEnumerable<string[]> ReadFileAsLinesSets(string fileName, int setLen = 10)
{
using (var reader = new StreamReader(fileName))
while (!reader.EndOfStream)
{
var set = new List<string>();
for (var i = 0; i < setLen && !reader.EndOfStream; i++)
{
set.Add(reader.ReadLine());
}
yield return set.ToArray();
}
}
... More fun version...
class Example
{
static void Main(string[] args)
{
"YourFile.txt".ReadAsLines()
.AsPaged(10)
.Select(a=>a.ToArray()) //required or else you will get random data since "WrappedEnumerator" is not thread safe
.AsParallel()
.WithDegreeOfParallelism(10)
.ForAll(a =>
{
//Do your work here.
Console.WriteLine(a.Aggregate(new StringBuilder(),
(sb, v) => sb.AppendFormat("{0:000000} ", v),
sb => sb.ToString()));
});
}
}
public static class ToolsEx
{
public static IEnumerable<IEnumerable<T>> AsPaged<T>(this IEnumerable<T> items,
int pageLength = 10)
{
using (var enumerator = new WrappedEnumerator<T>(items.GetEnumerator()))
while (!enumerator.IsDone)
yield return enumerator.GetNextPage(pageLength);
}
public static IEnumerable<T> GetNextPage<T>(this IEnumerator<T> enumerator,
int pageLength = 10)
{
for (var i = 0; i < pageLength && enumerator.MoveNext(); i++)
yield return enumerator.Current;
}
public static IEnumerable<string> ReadAsLines(this string fileName)
{
using (var reader = new StreamReader(fileName))
while (!reader.EndOfStream)
yield return reader.ReadLine();
}
}
internal class WrappedEnumerator<T> : IEnumerator<T>
{
public WrappedEnumerator(IEnumerator<T> enumerator)
{
this.InnerEnumerator = enumerator;
this.IsDone = false;
}
public IEnumerator<T> InnerEnumerator { get; private set; }
public bool IsDone { get; private set; }
public T Current { get { return this.InnerEnumerator.Current; } }
object System.Collections.IEnumerator.Current { get { return this.Current; } }
public void Dispose()
{
this.InnerEnumerator.Dispose();
this.IsDone = true;
}
public bool MoveNext()
{
var next = this.InnerEnumerator.MoveNext();
this.IsDone = !next;
return next;
}
public void Reset()
{
this.IsDone = false;
this.InnerEnumerator.Reset();
}
}

How to sort an arraylist on date?

Code:
while ((linevalue = filereader.ReadLine()) != null)
{
items.Add(linevalue);
}
filereader.Close();
items.Sort();
//To display the content of array (sorted)
IEnumerator myEnumerator = items.GetEnumerator();
while (myEnumerator.MoveNext())
{
Console.WriteLine(myEnumerator.Current);
}
The program above displays all the values. How to extract only the dates and sort it in ascending order?
I am not let to work with linq, use the exception or threading or any other stuff. I have to stick with the File Stream, try to get my data out of the text file, sort and store it, so that i can retrieve it, view it and edit it and search for any particular date and see the date of joining records for that date. Can't figure out. Struggling
Basically, don't try and work with the file as lines of text; separate that away, so that you have one piece of code which parses that text into typed records, and then process those upstream when you only need to deal with typed data.
For example (and here I'm assuming that the file is tab-delimited, but you could change it to be column indexed instead easily enough); look at how little work my Main method needs to do to work with the data:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
static class Program
{
static void Main()
{
foreach (var item in ReadFile("my.txt").OrderBy(x => x.Joined))
{
Console.WriteLine(item.Names);
}
}
static readonly char[] tab = { '\t' };
class Foo
{
public string Names { get; set; }
public int Age { get; set; }
public string Designation { get; set; }
public DateTime Joined { get; set; }
}
static IEnumerable<Foo> ReadFile(string path)
{
using (var reader = File.OpenText(path))
{
// skip the first line (headers), or exit
if (reader.ReadLine() == null) yield break;
// read each line
string line;
var culture = CultureInfo.InvariantCulture;
while ((line = reader.ReadLine()) != null)
{
var parts = line.Split(tab);
yield return new Foo
{
Names = parts[0],
Age = int.Parse(parts[1], culture),
Designation = parts[2],
Joined = DateTime.Parse(parts[3], culture)
};
}
}
}
}
And here's a version (not quite as elegant, but working) that works on .NET 2.0 (and probably on .NET 1.1) using only ISO-1 language features; personally I think it would be silly to use .NET 1.1, and if you are using .NET 2.0, then List<T> would be vastly preferable to ArrayList. But this is "worst case":
using System;
using System.Collections;
using System.Globalization;
using System.IO;
class Program
{
static void Main()
{
ArrayList items = ReadFile("my.txt");
items.Sort(FooByDateComparer.Default);
foreach (Foo item in items)
{
Console.WriteLine(item.Names);
}
}
class FooByDateComparer : IComparer
{
public static readonly FooByDateComparer Default
= new FooByDateComparer();
private FooByDateComparer() { }
public int Compare(object x, object y)
{
return ((Foo)x).Joined.CompareTo(((Foo)y).Joined);
}
}
static readonly char[] tab = { '\t' };
class Foo
{
private string names, designation;
private int age;
private DateTime joined;
public string Names { get { return names; } set { names = value; } }
public int Age { get { return age; } set { age = value; } }
public string Designation { get { return designation; } set { designation = value; } }
public DateTime Joined { get { return joined; } set { joined = value; } }
}
static ArrayList ReadFile(string path)
{
ArrayList items = new ArrayList();
using (StreamReader reader = File.OpenText(path))
{
// skip the first line (headers), or exit
if (reader.ReadLine() == null) return items;
// read each line
string line;
CultureInfo culture = CultureInfo.InvariantCulture;
while ((line = reader.ReadLine()) != null)
{
string[] parts = line.Split(tab);
Foo foo = new Foo();
foo.Names = parts[0];
foo.Age = int.Parse(parts[1], culture);
foo.Designation = parts[2];
foo.Joined = DateTime.Parse(parts[3], culture);
items.Add(foo);
}
}
return items;
}
}
I'm not sure why you'd want to retrieve just the dates. You'd probably be better reading your data into Tuples first. Something like
List<Tuple<string, int, string, DateTime>> items.
Then you can sort them by items.Item4, which will be the date.
You can use LINQ and split the line according to tabs to only retrieve the date and order them through a conversion to date.
while ((linevalue = filereader.ReadLine()) != null)
{
items.Add(linevalue.Split('\t').Last());
}
filereader.Close();
items.OrderBy(i => DateTime.Parse(i));
foreach(var item in items)
{
Console.WriteLine(item);
}
get the desired values in Array from the file...
public class DateComparer : IComparer {
public int Compare(DateTime x, DateTime y) {
if(x.Date > y.Date)
return 1;
if(x.Date < y.Date)
return -1;
else
return 0;
}
}
list.Sort(new DateComparer());

Sort XML Nodes by Alpha.Numeric using C#

Say I have an XmlDocument that I generate that has InnerXml that looks like this:
<ORM_O01>
<MSH>
<MSH.9>
<MSG.2>O01</MSG.2>
</MSH.9>
<MSH.6>
<HD.1>13702</HD.1>
</MSH.6>
</MSH>
<ORM_O01.PATIENT>
<PID>
<PID.18>
<CX.1>SecondTestFin</CX.1>
</PID.18>
<PID.3>
<CX.1>108</CX.1>
</PID.3>
</PID>
</ORM_O01.PATIENT>
</ORM_O01>
As you can see node <PID.18> is before node <PID.3>. (<MSH.9> is also before <MSH.6>.)
Restructuring my generation would cause my nice clean code to become very messy.
Is there a way to sort the nodes so that it will sort alpha until it hits the last period then sort numeric (if the last values are numbers)?
By "numeric sorting" I mean it will look at the whole number rather than char by char. (So 18 > 3).
The obvious answer is yes.
If this is the result you want:
<ORM_O01>
<MSH>
<MSH.6>
<HD.1>13702</HD.1>
</MSH.6>
<MSH.9>
<MSG.2>O01</MSG.2>
</MSH.9>
</MSH>
<ORM_O01.PATIENT>
<PID>
<PID.3>
<CX.1>108</CX.1>
</PID.3>
<PID.18>
<CX.1>SecondTestFin</CX.1>
</PID.18>
</PID>
</ORM_O01.PATIENT>
</ORM_O01>
Then this class will do it: (I should get paid for this...)
using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace Test
{
public class SortXmlFile
{
XElement rootNode;
public SortXmlFile(FileInfo file)
{
if (file.Exists)
rootNode = XElement.Load(file.FullName);
else
throw new FileNotFoundException(file.FullName);
}
public XElement SortFile()
{
SortElements(rootNode);
return rootNode;
}
public void SortElements(XElement root)
{
bool sortWithNumeric = false;
XElement[] children = root.Elements().ToArray();
foreach (XElement child in children)
{
string name;
int value;
// does any child need to be sorted by numeric?
if (!sortWithNumeric && Sortable(child, out name, out value))
sortWithNumeric = true;
child.Remove(); // we'll re-add it in the sort portion
// sorting child's children
SortElements(child);
}
// re-add children after sorting
// sort by name portion, which is either the full name,
// or name that proceeds period that has a numeric value after the period.
IOrderedEnumerable<XElement> childrenSortedByName = children
.OrderBy(child =>
{
string name;
int value;
Sortable(child, out name, out value);
return name;
});
XElement[] sortedChildren;
// if needed to sort numerically
if (sortWithNumeric)
{
sortedChildren = childrenSortedByName
.ThenBy(child =>
{
string name;
int value;
Sortable(child, out name, out value);
return value;
})
.ToArray();
}
else
sortedChildren = childrenSortedByName.ToArray();
// re-add the sorted children
foreach (XElement child in sortedChildren)
root.Add(child);
}
public bool Sortable(XElement node, out string name, out int value)
{
var dot = new char[] { '.' };
name = node.Name.ToString();
if (name.Contains("."))
{
string[] parts = name.Split(dot);
if (Int32.TryParse(parts[1], out value))
{
name = parts[0];
return true;
}
}
value = -1;
return false;
}
}
}
Someone may be able to write this cleaner and meaner, but this should get you going.
Was interested in your question so here is my two cents.
I've implemented IComparer<T> to handle the element comparisons and two methods which handle recursion. The code could be cleaned up a bit but I've pasted in the console application code I created to show you my solution which I think worked out well.
Edit: To make this easier to read I've broken this down into the core parts though I've left the functional console app
IComparer<T> Implementation:
public class SplitComparer : IComparer<string>
{
public int Compare(string x, string y)
{
var partsOfX = x.Split('.');
int firstNumber;
if (partsOfX.Length > 1 && int.TryParse(partsOfX[1], out firstNumber))
{
var secondNumber = Convert.ToInt32(y.Split('.')[1]);
return firstNumber.CompareTo(secondNumber);
}
return x.CompareTo(y);
}
}
Methods for handling the recursion:
private static XElement Sort(XElement element)
{
var xe = new XElement(element.Name, element.Elements().OrderBy(x => x.Name.ToString(), new SplitComparer()).Select(x => Sort(x)));
if (!xe.HasElements)
{
xe.Value = element.Value;
}
return xe;
}
private static XDocument Sort(XDocument file)
{
return new XDocument(Sort(file.Root));
}
Functional Console Application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Xml.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var xml = #"<ORM_O01>
<ORM_O01.PATIENT>
<PID>
<PID.18>
<CX.1>SecondTestFin</CX.1>
</PID.18>
<PID.3>
<CX.1>108</CX.1>
</PID.3>
</PID>
</ORM_O01.PATIENT>
<MSH>
<MSH.9>
<MSG.2>O01</MSG.2>
</MSH.9>
<MSH.6>
<HD.1>13702</HD.1>
</MSH.6>
</MSH>
</ORM_O01>";
var xDoc = XDocument.Parse(xml);
var result = Sort(xDoc);
Console.WriteLine(result.ToString());
Console.Read();
}
private static XElement Sort(XElement element)
{
var xe = new XElement(element.Name, element.Elements().OrderBy(x => x.Name.ToString(), new SplitComparer()).Select(x => Sort(x)));
if (!xe.HasElements)
{
xe.Value = element.Value;
}
return xe;
}
private static XDocument Sort(XDocument file)
{
return new XDocument(Sort(file.Root));
}
}
public class SplitComparer : IComparer<string>
{
public int Compare(string x, string y)
{
var partsOfX = x.Split('.');
int firstNumber;
if (partsOfX.Length > 1 && int.TryParse(partsOfX[1], out firstNumber))
{
var secondNumber = Convert.ToInt32(y.Split('.')[1]);
return firstNumber.CompareTo(secondNumber);
}
return x.CompareTo(y);
}
}
}
utilizing System.Xml.Linq, this code may help you.
Usage:
string xmlString=
#"
....your string.....
";
XDocument xDoc = XDocument.Load(new StringReader(xmlString));
XDocument newXDoc = SortXml(xDoc);
Console.WriteLine(newXDoc);
SortXml function:
XDocument SortXml(XDocument xDoc)
{
Func<XElement, string> keyBuilder =
s => s.Name.ToString().Split('.')
.Aggregate("",(sum, str) => sum += str.PadLeft(32,' '));
XElement root = new XElement(xDoc.Root.Name);
SortXml(root, xDoc.Elements(), keyBuilder);
return new XDocument(root);
}
void SortXml(XElement newXDoc, IEnumerable<XElement> elems, Func<XElement, string> keyBuilder)
{
foreach (var newElem in elems.OrderBy(e => keyBuilder(e)))
{
XElement t = new XElement(newElem);
t.RemoveNodes();
newXDoc.Add(t);
SortXml(t, newElem.Elements(), keyBuilder);
}
}
Yet another attempt, using a modified Dotnet.Commons.Xml.
Get the XmlUtils class here.
Create a custom Comparer that has all your logic (this will get you going)
public class CustomComparer : IComparer
{
public int Compare(object x, object y)
{
string o1 = x as string;
string o2 = y as string;
string[] parts1 = o1.Split('.');
string[] parts2 = o2.Split('.');
// Assuming first part is alpha, last part is numeric and both of them has second part. Otherwise compare original ones.
if (parts1.Length < 2 || parts2.Length < 2)
return o1.CompareTo(o2);
if (parts1[0].Equals(parts2[0]))
{
// Do a numeric compare
return int.Parse(parts1[parts1.Length - 1]).CompareTo(int.Parse(parts2[parts2.Length - 1]));
}
else
{
// Just compare the first part
return parts1[0].CompareTo(parts2[0]);
}
}
Then modify the XmlUtils SortElements function, add this to the top:
CustomComparer comparer = new CustomComparer();
and change the line:
if (String.Compare(node.ChildNodes[i].Name, node.ChildNodes[i-1].Name, true) < 0)
to
if (comparer.Compare(node.ChildNodes[i].Name, node.ChildNodes[i - 1].Name) < 0)
Would this solution from Java2S.com be of any use?

Categories