Sorting issue in .NET - c#

I am using this linq query to sort a string column but the results I am getting does not seems to be in right order?
Query:
userList = users.OrderBy(u => u.FirstName)
.Skip(offset)
.Take(rowcount)
.ToList<User>();
Result:
rama &
11Rama
15rama
1Rama
2Rama
490110rama
IU-Rama
Rama
it should be something like?
1Rama
2Rama
11Rama
15rama
490110rama
IU-Rama
rama &
Rama

You are getting your result sorted by the code points of the characters and that is by far the most common implementation for sorting strings. What you are expecting is called natural sort order, see for example this article, but you will have to do it on your own because .NET does not provide this out of the box.

By adding this code you will be able to sort as you need it to be done. But this sorting will be done on client side and all records must be fetch as list.
userList = users.ToList<User>()
.OrderBy(u => u.FirstName,new NumericComparer())
.Skip(offset)
.Take(rowcount)
.ToList<User>();
public class NumericComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return StringLogicalComparer.Compare(x, y);
}
}
public class StringLogicalComparer
{
public static int Compare(string s1, string s2)
{
//get rid of special cases
if ((s1 == null) && (s2 == null)) return 0;
if (s1 == null) return -1;
if (s2 == null) return 1;
if ((s1.Equals(string.Empty) && (s2.Equals(string.Empty)))) return 0;
if (s1.Equals(string.Empty)) return -1;
if (s2.Equals(string.Empty)) return -1;
//WE style, special case
bool sp1 = Char.IsLetterOrDigit(s1, 0);
bool sp2 = Char.IsLetterOrDigit(s2, 0);
if (sp1 && !sp2) return 1;
if (!sp1 && sp2) return -1;
int i1 = 0, i2 = 0; //current index
while (true)
{
bool c1 = Char.IsDigit(s1, i1);
bool c2 = Char.IsDigit(s2, i2);
int r; // temp result
if (!c1 && !c2)
{
bool letter1 = Char.IsLetter(s1, i1);
bool letter2 = Char.IsLetter(s2, i2);
if ((letter1 && letter2) || (!letter1 && !letter2))
{
r = letter1 ? Char.ToLower(s1[i1]).CompareTo(Char.ToLower(s2[i2])) : s1[i1].CompareTo(s2[i2]);
if (r != 0) return r;
}
else if (!letter1) return -1;
else return 1;
}
else if (c1 && c2)
{
r = CompareNum(s1, ref i1, s2, ref i2);
if (r != 0) return r;
}
else if (c1)
{
return -1;
}
else
{
return 1;
}
i1++;
i2++;
if ((i1 >= s1.Length) && (i2 >= s2.Length))
{
return 0;
}
if (i1 >= s1.Length)
{
return -1;
}
if (i2 >= s2.Length)
{
return -1;
}
}
}
private static int CompareNum(string s1, ref int i1, string s2, ref int i2)
{
int nzStart1 = i1, nzStart2 = i2; // nz = non zero
int end1 = i1, end2 = i2;
ScanNumEnd(s1, i1, ref end1, ref nzStart1);
ScanNumEnd(s2, i2, ref end2, ref nzStart2);
int start1 = i1; i1 = end1 - 1;
int start2 = i2; i2 = end2 - 1;
int nzLength1 = end1 - nzStart1;
int nzLength2 = end2 - nzStart2;
if (nzLength1 < nzLength2) return -1;
if (nzLength1 > nzLength2) return 1;
for (int j1 = nzStart1, j2 = nzStart2; j1 <= i1; j1++, j2++)
{
int r = s1[j1].CompareTo(s2[j2]);
if (r != 0) return r;
}
// the nz parts are equal
int length1 = end1 - start1;
int length2 = end2 - start2;
if (length1 == length2) return 0;
if (length1 > length2) return -1;
return 1;
}
private static void ScanNumEnd(string s, int start, ref int end, ref int nzStart)
{
nzStart = start;
end = start;
bool countZeros = true;
while (Char.IsDigit(s, end))
{
if (countZeros && s[end].Equals('0'))
{
nzStart++;
}
else countZeros = false;
end++;
if (end >= s.Length) break;
}
}
}

Creating a custom IComparer would work for you.
Check this implementation: http://zootfroot.blogspot.com/2009/09/natural-sort-compare-with-linq-orderby.html
You code would then call myLinqQuery.OrderBy(item => item.sortProperty, new MyComparer<string>())
In his example, the sort order return:
image1.jpg
image4.jpg
image30.jpg
image200.jpg

Related

Algorithm for the implementation of merge sort using link array(pointers)

int a[SIZE];
int link[SIZE];
int MergeLists(int i, int j)
{
int head;
int *pprev = &head;
while((i != -1) && (j != -1)){
if(a[i] <= a[j]){
*pprev = i;
pprev = &link[i];
i=*pprev;
} else {
*pprev = j;
pprev = &link[j];
j=*pprev;
}
}
if(i == -1)
*pprev=j;
else
*pprev=i;
printf("%d head",head);
return head;
}
int MergeSort(int low, int end)
{
int mid, i, j;
if((end - low) == 0){
return low;
}
if((end - low) == 1){
link[low] = -1;
return low;
}
if((end - low) == 2){
if(a[low] <= a[end-1]){
link[low] = end-1;
link[end-1] = -1;
return low;
} else {
link[end-1] = low;
link[low] = -1;
return end-1;
}
}
mid = (low+end)/2;
i = MergeSort(low, mid);
j = MergeSort(mid, end);
return MergeLists(i, j);
}
int main()
{
int i;
for(i=0;i<SIZE;++i)
{
printf("\nenter element number %d: ",i+1);
scanf("%d",&a[i]);
}
i = MergeSort(1, SIZE);
do{
printf("%3d", a[i]);
i = link[i];
}while(i != -1);
return 0;
}
to implement merge sort using link array(pinters)
error is given below
input 4 5 2 1
output 1 2 5
MergeLists() uses head for the start of a list (the old code uses link[0]), and -1 for the end of a list (the old code uses 0). This allows sorting of a[0] to a[n-1] (the old code was sorting a[1] to a[n], with a[0] unused).
Well, it seems to be a minor problem, just change the function call in main to
i = MergeSort(0, SIZE);
In C or C++, the index starts with 0, and it is also true when we try to write a function.

Quick Sort using C#

Hello I trying to do a QuickSort but didn't appear the result, For example the user input "cdabe" so the expected result is "abcde". May I know what is the cause why the result didn't display?
because There is no error in the code. I'm using MVC. My MergeSort is working properly but my QuickSort didn't.
Model :
public string QuickSort()
{
string arrangedSort = "";
string Word= "cdabe";
List<string> ListLetters = new List<string>();
for (int i = 0; i < Word.Length; i++)
{
ListLetters.Add(Word.Substring(i, 1));
}
aQuicksort(Word, 0, ListLetters.Count - 1);
void aQuicksort(string Word, int left, int right)
{
int i = left;
int j = right;
var pivot = Word[(left + right) / 2];
while (i <= j)
{
while (char.Parse(ListLetters[i]) < pivot)
i++;
while (char.Parse(ListLetters[i]) > pivot)
j--;
if (i <= j)
{
var tmp = ListLetters[i];
ListLetters[i] = ListLetters[j];
ListLetters[j] = tmp;
i++;
j--;
}
}
if (left < j)
aQuicksort(Word, left, j);
if (i < right)
aQuicksort(Word, i, right);
foreach (var listLetter in ListLetters)
{
arrangedSort += listLetter;
}
}
return arrangedSort;
}
Try this implementation, it uses LinQ using System.linq
public static IEnumerable<int> QSort3(IEnumerable<int> source)
{
if (!source.Any())
return source;
int first = source.First();
QSort3Helper myHelper =
source.GroupBy(i => i.CompareTo(first))
.Aggregate(new QSort3Helper(), (a, g) =>
{
if (g.Key == 0)
a.Same = g;
else if (g.Key == -1)
a.Less = g;
else if (g.Key == 1)
a.More = g;
return a;
});
IEnumerable<int> myResult = Enumerable.Empty<int>();
if (myHelper.Less != null)
myResult = myResult.Concat(QSort3(myHelper.Less));
if (myHelper.Same != null)
myResult = myResult.Concat(myHelper.Same);
if (myHelper.More != null)
myResult = myResult.Concat(QSort3(myHelper.More));
return myResult;
}
public class QSort3Helper
{
public IEnumerable<int> Less;
public IEnumerable<int> Same;
public IEnumerable<int> More;
}
code from this post

Largest substring composed of identical characters

I want to develop method that will return the length of largest substring composed of identical characters form string that is passed as argument, but without using any of .NET libraries.
For example if we pass aaacccccdefffgg as parameter the biggest substring is ccccc and method should return 5.
Here is my working solution :
public static int GetMaxSubstringLenght(char[] myArray)
{
int max = 0;
for (int i = 0; i < myArray.Length-1; i++)
{
if (myArray.Length == 0)
{
return 0;
}
else
{
int j = i + 1;
int currentMax = 1; // string has some value, so we start with 1
while (myArray[i] == myArray[j])
{
currentMax++;
if (max < currentMax)
{
max = currentMax;
}
j++;
}
}
}
return max;
}
The code above will return expected result, but there will be some unnecessary iteration in for loop that I want to avoid. In first iteration when i=0it will compare it until j=2 and then will get out of while loop and start second iteration in for loop comparing the one at [1] index with [2], which we already did in previous iteration.So basically, when first iteration is completed, next one should start from the last value of j. How can I achieve that ?
Thank You in advance.
Since you want "Largest substring..." let's take String as argument and return String
public static String GetMaxSubstring(String value) {
if (String.IsNullOrEmpty(value))
return "";
int bestCount = 0;
char bestChar = '\0';
int currentCount = 0;
char current = '\0';
for (int i = 0; i < value.Length; ++i) {
if ((i == 0) || (value[i] != current))
currentCount = 0;
currentCount += 1;
current = value[i];
if (currentCount > bestCount) {
bestCount = currentCount;
bestChar = current;
}
}
return new String(bestChar, bestCount);
}
....
// "ccccc"
String result = GetMaxSubstring("aaacccccdefffgg");
// 5
int length = result.Length;
Another approach:
public static int MaxSubstringLength(string s)
{
if (string.IsNullOrEmpty(s))
return 0;
int max = 0, cur = 1;
for (int i = 1; i < s.Length; ++i, ++cur)
{
if (s[i] != s[i-1])
{
max = cur > max ? cur : max;
cur = 0;
}
}
return cur > max ? cur : max;
}
[EDIT] Simplified the code.
[EDIT2] Simplified the code further.
you also can do it with one loop:
public static int GetMaxSubstringLenght(char[] myArray)
{
int max = 0;
char currentchar = myArray[0];
int count = 1;
for each(char c in myArray)
{
if(currentchar != c)
{
count = 1;
currentchar = c;
}
if(count > max)
{
max = count;
}
count++;
}
return max;
}
I changed the code... now this code does not use math.max and I think I eleminated the mistake... I've no IDE at the moment to test it
public static int GetMaxSubstringLenght(char[] myArray)
{
if (myArray.Length == 0)
return 0;
if (myArray.Length == 1)
return 1;
int max = 1;
int localMax = 1;
for (int i = 0; i < myArray.Length - max; i++ )
{
if (myArray[i] == myArray[i + 1])
{
localMax++;
}
else
{
max = Math.Max(max, localMax);
localMax = 1;
}
}
return Math.Max(max, localMax);
}
static int LongestCharSequence(string s)
{
if (string.IsNullOrEmpty(s)) return 0;
var prevChar = '\0';
int cmax = 0;
int max = 1;
foreach (char c in s)
{
if (c != prevChar)
{
cmax = 1;
prevChar = c;
}
else
{
if (++cmax > max) max = cmax;
}
}
return max;
}
recursion!
static int LongestCharSequence(string s)
{
int i = (s?.Length ?? 0) == 0 ? 0 : 1;
for (; i < s?.Length; i++)
if (s[i] != s[i - 1]) return Math.Max(i, LongestCharSequence(s.Substring(i)));
return i;
}
Another solution using my favorite nested loop technique:
public static int MaxSubstringLength(string s)
{
int maxLength = 0;
for (int length = s != null ? s.Length : 0, pos = 0; pos < length;)
{
int start = pos;
while (++pos < length && s[pos] == s[start]) { }
maxLength = Math.Max(maxLength, pos - start);
}
return maxLength;
}

Is there any better way to compare these values in C#?

I have method for comparing values like this:
protected bool CompareValues(string a="", int b=0, string c="", int d=0, string e="", int f=0)
{
int counter = 0;
if(int.Parse(a) > b)
{
counter++;
}
if(int.Parse(c) > d)
{
counter++;
}
if(counter > 1)
{
counter = 1;
}
if(int.Parse(e) > f)
{
counter++;
}
if(counter > 1)
{
return true;
}
else
{
return false;
}
}
It works fine for me, but I am can't stand without thinking about some improvement if possible. Any suggestion would be appreciate.
If you need to perform n-many comparisons of the form
(int.Parse(a1) > b1 || int.Parse(a2) > b2 || ... || int.Parse(aK) > bK) && int.Parse(aN) > bN
You can make a method that just accepts a set of pairs of values to compare
protected bool CompareValues(params Tuple<string, int>[] comparisons)
{
if(ReferenceEquals(comparisons, null))
{
throw new ArgumentNullException("comparisons");
}
if(comparisons.Length < 1)
{
throw new ArgumentException("At least one pair to compare must be specified");
}
var atLeastOneComparisonSucceeded = comparisons.Length == 1;
for(var i = 0; !atLeastOneComparisonSucceeded && i < comparisons.Length - 1; ++i)
{
atLeastOneComparisonSucceeded = int.Parse(comparisons[i].Item1) > comparisons[i].Item2;
}
var lastIndex = comparisons.Length - 1;
return atLeastOneComparisonSucceeded && int.Parse(comparisons[lastIndex].Item1) > comparisons[lastIndex].Item2;
}
Usage:
var result = CompareValues(new Tuple<string, int>("5", 2),
new Tuple<string, int>("3", 1),
new Tuple<string, int>("1", 2));
If you only ever need 3 pairs of values (as in your original post), you could provide overloads for the method that provided appropriate default values, like this
protected static bool CompareValues(string a, int b)
{
return CompareValues(a, b, "1", 0);
}
protected static bool CompareValues(string a, int b, string c, int d)
{
return CompareValues(a, b, c, d, "1", 0);
}
protected static bool CompareValues(string a, int b, string c, int d, string e, int f)
{
return ((int.Parse(a) > b || int.Parse(c) > d) && int.Parse(e) > f);
}
Of course, the arguments passed down from the overloads must be chosen such that the semantics are appropriate.
I am not sure in the middle why you reset counter to 1, however this is what I understood
if((int.Parse(a) > b || int.Parse(c) > d) && int.Parse(e) > f)
{
return true;
}
else
{
return false;
}
It looks like you want:
return (int.Parse(a) > b || int.Parse(c) > d) && int.Parse(e) > f;
I'm not sure but is this what you are trying to do?
return ( ( int.Parse(a) > b || int.Parse(c) > d ) && int.Parse(e) > f);

What is the C# equivalent of BitSet of Java?

My requirements are simple:
Be able to define dimensions of bit array, i.e: 5 bytes.
bool Get(bitIndex: int)
Set(bitIndex: int)
Is there a c# equivalent which provides similar functionality to BitSet in Java?
Here's the scenario:
Initialize 5 bytes, all bits are 0(false).
Set byte 3, bit 8 to TRUE.
Get status of byte 3, bit 8.
UPDATE: Solution from Michael Bray:
static void Main(string[] args)
{
// Set for 5 bytes
BitArray ba = new BitArray(8 * 5);
// Set bit #1 on byte #4
ba.Set(GetBitNum(4, 1), true);
// Get bit #1 on byte #4
bool v = ba.Get(GetBitNum(4, 1));
}
static int GetBitNum(int byteNum, int bitNum) // Assumes index starts at 1
{
return (byteNum - 1) * 8 + (bitNum - 1);
}
System.Collections.BitArray is pretty close, but it's a bit lacking in features. I wrote a helper class that implements a lot of features you might need for BitArray some time ago, but I'd have to dig it up. Let me know if you think you need it.
EDIT: As requested in the comments below, I've posted the code at http://pastebin.com/GLyzcUZC. As I discuss, though, it's benefits over stock BitArray are minimal, as I wrote it for some specific needs that I had. Do with it as you wish.
EDIT 2: As Miguel pointed out in the comments, there are some implementation issues that make my 'BitArray' code not so good... I had already realized the deficiencies and had re-written a new version called BoolArray (to distinguish from BitArray) that doesn't suffer from those problems :
namespace Utils
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Threading;
/// <summary>
/// A replacement for BitArray
/// </summary>
public class BoolArray : IEnumerable, ICollection, ICloneable
{
private UInt32[] bits = null;
private int _length = 0;
private static UInt32 ONE = (UInt32)1 << 31;
private object _syncRoot;
private static Func<byte[], byte[]> EndianFixer = null;
#region Constructors
static BoolArray()
{
if (BitConverter.IsLittleEndian) EndianFixer = (a) => a.Reverse().ToArray();
else EndianFixer = (a) => a;
}
public BoolArray(BoolArray srcBits)
{
this.InitializeFrom(srcBits.ToArray());
}
public BoolArray(BitArray srcBits)
{
this._length = srcBits.Count;
this.bits = new UInt32[RequiredSize(this._length)];
for (int i = 0; i < srcBits.Count; i++) this[i] = srcBits[i];
}
public BoolArray(int v)
{
ICollection<byte> bytes = EndianFixer(BitConverter.GetBytes(v)).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<bool> srcBits)
{
this.InitializeFrom(srcBits.ToArray());
}
public BoolArray(ICollection<byte> srcBits)
{
InitializeFrom(srcBits);
}
public BoolArray(ICollection<short> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<ushort> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<int> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<uint> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<long> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<ulong> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(int capacity, bool defaultValue = false)
{
this.bits = new UInt32[RequiredSize(capacity)];
this._length = capacity;
// Only need to do this if true, because default for all bits is false
if (defaultValue) for (int i = 0; i < this._length; i++) this[i] = true;
}
private void InitializeFrom(ICollection<byte> srcBits)
{
this._length = srcBits.Count * 8;
this.bits = new UInt32[RequiredSize(this._length)];
for (int i = 0; i < srcBits.Count; i++)
{
uint bv = srcBits.Skip(i).Take(1).Single();
for (int b = 0; b < 8; b++)
{
bool bitVal = ((bv << b) & 0x0080) != 0;
int bi = 8 * i + b;
this[bi] = bitVal;
}
}
}
private void InitializeFrom(ICollection<bool> srcBits)
{
this._length = srcBits.Count;
this.bits = new UInt32[RequiredSize(this._length)];
int index = 0;
foreach (var b in srcBits) this[index++] = b;
}
private static int RequiredSize(int bitCapacity)
{
return (bitCapacity + 31) >> 5;
}
#endregion
public bool this[int index]
{
get
{
if (index >= _length) throw new IndexOutOfRangeException();
int byteIndex = index >> 5;
int bitIndex = index & 0x1f;
return ((bits[byteIndex] << bitIndex) & ONE) != 0;
}
set
{
if (index >= _length) throw new IndexOutOfRangeException();
int byteIndex = index >> 5;
int bitIndex = index & 0x1f;
if (value) bits[byteIndex] |= (ONE >> bitIndex);
else bits[byteIndex] &= ~(ONE >> bitIndex);
}
}
#region Interfaces implementation
#region IEnumerable
public IEnumerator GetEnumerator()
{
//for (int i = 0; i < _length; i++) yield return this[i];
return this.ToArray().GetEnumerator();
}
#endregion
#region ICollection
public void CopyTo(Array array, int index)
{
if (array == null) throw new ArgumentNullException("array");
if (index < 0) throw new ArgumentOutOfRangeException("index");
if (array.Rank != 1) throw new ArgumentException("Multidimensional array not supported");
if (array is UInt32[]) Array.Copy(this.bits, 0, array, index, (this.Count + sizeof(UInt32) - 1) / sizeof(UInt32));
else if (array is bool[]) Array.Copy(this.ToArray(), 0, array, index, this.Count);
else throw new ArgumentException("Array type not supported (UInt32[] or bool[] only)");
}
public int Count
{
get { return this._length; }
private set
{
if (value > this._length) Extend(value - this._length);
else this._length = Math.Max(0, value);
}
}
public bool IsSynchronized
{
get { return false; }
}
public object SyncRoot
{
get
{
if (this._syncRoot == null) Interlocked.CompareExchange<object>(ref this._syncRoot, new object(), null);
return _syncRoot;
}
}
#endregion
#region ICloneable
public object Clone()
{
return new BoolArray(this);
}
// Not part of ICloneable, but better - returns a strongly-typed result
public BoolArray Dup()
{
return new BoolArray(this);
}
#endregion
#endregion
#region String Conversions
public override string ToString()
{
return ToBinaryString();
//return ToHexString(" ", " ■ ");
}
public static BoolArray FromHexString(string hex)
{
if (hex == null) throw new ArgumentNullException("hex");
List<bool> bits = new List<bool>();
for (int i = 0; i < hex.Length; i++)
{
int b = byte.Parse(hex[i].ToString(), NumberStyles.HexNumber);
bits.Add((b >> 3) == 1);
bits.Add(((b & 0x7) >> 2) == 1);
bits.Add(((b & 0x3) >> 1) == 1);
bits.Add((b & 0x1) == 1);
}
BoolArray ba = new BoolArray(bits.ToArray());
return ba;
}
public string ToHexString(string bitSep8 = null, string bitSep128 = null)
{
string s = string.Empty;
int b = 0;
bool[] bbits = this.ToArray();
for (int i = 1; i <= bbits.Length; i++)
{
b = (b << 1) | (bbits[i - 1] ? 1 : 0);
if (i % 4 == 0)
{
s = s + string.Format("{0:x}", b);
b = 0;
}
if (i % (8 * 16) == 0)
{
s = s + bitSep128;
}
else if (i % 8 == 0)
{
s = s + bitSep8;
}
}
int ebits = bbits.Length % 4;
if (ebits != 0)
{
b = b << (4 - ebits);
s = s + string.Format("{0:x}", b);
}
return s;
}
public static BoolArray FromBinaryString(string bin, char[] trueChars = null)
{
if (trueChars == null) trueChars = new char[] { '1', 'Y', 'y', 'T', 't' };
if (bin == null) throw new ArgumentNullException("bin");
BoolArray ba = new BoolArray(bin.Length);
for (int i = 0; i < bin.Length; i++) ba[i] = bin[i].In(trueChars);
return ba;
}
public string ToBinaryString(char setChar = '1', char unsetChar = '0')
{
return new string(this.ToArray().Select(v => v ? setChar : unsetChar).ToArray());
}
#endregion
#region Class Methods
public bool[] ToArray()
{
bool[] vbits = new bool[this._length];
for (int i = 0; i < _length; i++) vbits[i] = this[i];
return vbits;
}
public BoolArray Append(ICollection<bool> addBits)
{
int startPos = this._length;
Extend(addBits.Count);
bool[] bitArray = addBits.ToArray();
for (int i = 0; i < bitArray.Length; i++) this[i + startPos] = bitArray[i];
return this;
}
public BoolArray Append(BoolArray addBits)
{
return this.Append(addBits.ToArray());
}
public static BoolArray Concatenate(params BoolArray[] bArrays)
{
return new BoolArray(bArrays.SelectMany(ba => ba.ToArray()).ToArray());
}
private void Extend(int numBits)
{
numBits += this._length;
int reqBytes = RequiredSize(numBits);
if (reqBytes > this.bits.Length)
{
UInt32[] newBits = new UInt32[reqBytes];
this.bits.CopyTo(newBits, 0);
this.bits = newBits;
}
this._length = numBits;
}
public bool Get(int index)
{
return this[index];
}
public BoolArray GetBits(int startBit = 0, int numBits = -1)
{
if (numBits == -1) numBits = bits.Length;
return new BoolArray(this.ToArray().Skip(startBit).Take(numBits).ToArray());
}
public BoolArray Repeat(int numReps)
{
bool[] oBits = this.ToArray();
List<bool> nBits = new List<bool>();
for(int i=0; i<numReps; i++) nBits.AddRange(oBits);
this.InitializeFrom(nBits);
return this;
}
public BoolArray Reverse()
{
int n = this.Count;
for(int i=0; i<n/2; i++)
{
bool b1 = this[i];
this[i] = this[n - i - 1];
this[n - i - 1] = b1;
}
return this;
}
public BoolArray Set(int index, bool v)
{
this[index] = v;
return this;
}
public BoolArray SetAll(bool v)
{
for (int i = 0; i < this.Count; i++) this[i] = v;
return this;
}
public BoolArray SetBits(ICollection<bool> setBits, int destStartBit = 0, int srcStartBit = 0, int numBits = -1, bool allowExtend = false)
{
if (setBits == null) throw new ArgumentNullException("setBits");
if ((destStartBit < 0) || (destStartBit >= this.Count)) throw new ArgumentOutOfRangeException("destStartBit");
if ((srcStartBit < 0) || (srcStartBit >= setBits.Count)) throw new ArgumentOutOfRangeException("srcStartBit");
bool[] sBits;
if (setBits is bool[]) sBits = (bool[])setBits;
else sBits = setBits.ToArray();
if (numBits == -1) numBits = setBits.Count;
if (numBits > (setBits.Count - srcStartBit)) numBits = setBits.Count - srcStartBit;
int diffSize = numBits - (this.Count - destStartBit);
if (diffSize > 0)
{
if (allowExtend) Extend(diffSize);
else numBits = this.Count - destStartBit;
}
for (int i = 0; i < numBits; i++) this[destStartBit + i] = sBits[srcStartBit + i];
return this;
}
public List<BoolArray> SplitEvery(int numBits)
{
int i = 0;
List<BoolArray> bitSplits = new List<BoolArray>();
while (i < this.Count)
{
bitSplits.Add(this.GetBits(i, numBits));
i += numBits;
}
return bitSplits;
}
public byte[] ToBytes(int startBit = 0, int numBits = -1)
{
if (numBits == -1) numBits = this._length - startBit;
BoolArray ba = GetBits(startBit, numBits);
int nb = (numBits + 7) / 8;
byte[] bb = new byte[nb];
for (int i = 0; i < ba.Count; i++)
{
if (!ba[i]) continue;
int bp = 7 - (i % 8);
bb[i / 8] = (byte)((int)bb[i / 8] | (1 << bp));
}
return bb;
}
#endregion
#region Logical Bitwise Operations
public BoolArray BinaryBitwiseOp(Func<bool, bool, bool> op, BoolArray ba, int start = 0)
{
for (int i = 0; i < ba.Count; i++)
{
if (start + i >= this.Count) break;
this[start + i] = op(this[start + i], ba[i]);
}
return this;
}
public BoolArray Xor(BoolArray xor, int start = 0)
{
return BinaryBitwiseOp((a, b) => (a ^ b), xor, start);
}
public BoolArray And(BoolArray and, int start = 0)
{
return BinaryBitwiseOp((a, b) => (a & b), and, start);
}
public BoolArray Or(BoolArray or, int start = 0)
{
return BinaryBitwiseOp((a, b) => (a | b), or, start);
}
public BoolArray Not(int start = 0, int len = -1)
{
for (int i = start; i < this.Count; i++)
{
if (--len == -1) break;
this[i] = !this[i];
}
return this;
}
#endregion
#region Class Operators
public static BoolArray operator +(BoolArray a, BoolArray b)
{
return a.Dup().Append(b);
}
public static BoolArray operator |(BoolArray a, BoolArray b)
{
return a.Dup().Or(b);
}
public static BoolArray operator &(BoolArray a, BoolArray b)
{
return a.Dup().And(b);
}
public static BoolArray operator ^(BoolArray a, BoolArray b)
{
return a.Dup().Xor(b);
}
public static BoolArray operator ~(BoolArray a)
{
return a.Dup().Not();
}
public static BoolArray operator <<(BoolArray a, int shift)
{
return a.Dup().Append(new bool[shift]);
}
public static BoolArray operator >>(BoolArray a, int shift)
{
return new BoolArray(a.ToArray().Take(Math.Max(0, a.Count - shift)).ToArray());
}
public static bool operator ==(BoolArray a, BoolArray b)
{
if (a.Count != b.Count) return false;
for (int i = 0; i < a.Count; i++) if (a[i] != b[i]) return false;
return true;
}
public override bool Equals(object obj)
{
if (!(obj is BoolArray)) return false;
return (this == (BoolArray)obj);
}
public override int GetHashCode()
{
return this.ToHexString().GetHashCode();
}
public static bool operator !=(BoolArray a, BoolArray b)
{
return !(a == b);
}
#endregion
}
}
I had the same issue, but had more than just the one Cardinality method to convert. So, I opted to port the entire BitSet class. Fortunately it was self-contained.
Here is the Gist of the C# port.
I have also added it to the open source BoboBrowse.Net project.
I have also ported the version from Apache Harmony (which is essentially a carbon copy of the JDK) and added it to the general library J2N so it is easy to consume.

Categories

Resources