How to check if all strings in array are the same length c# - c#

for instance,
string[] text=new string[] {"string1", "string2", "string3"};
how do i know if all string's length in this array are equal?

Another solution:
bool allSameLength = !text.Any(t => t.Length != text[0].Length));

Here is a solution without using for(each) as requested:
string[] text = new string[] {"dsasaffasfasfafsa", "siuuuuu", "ewqewqeqeqewqeq"};
int index = 0, firstLength = -1;
bool allSameLength = true;
while(index < text.Length)
{
int length = (text[index] + '\0').IndexOf('\0');
firstLength = (index == 0) ? length : firstLength;
allSameLength &= (length != firstLength) ;
index += 1;
}
return allSameLength;

Here is another solution that does not use for(each) and does not try to cheat by using a different type of loop (like while):
string[] text = new string[] {"dsasaffasfasfafsa", "siuuuuu", "ewqewqeqeqewqeq"};
List<string> texts = new List<string>();
texts.Add(null);
texts.AddRange(text);
texts.Add(null);
bool CheckSameLength(int index)
=> (texts[index + 1] == null) ? true
: texts[index] == null ? CheckSameLength(1)
: texts[index].Length == texts[index + 1].Length ? CheckSameLength(index + 1)
: false;
return CheckSameLength(texts, 0);

Most ridiculous use of recursion?
public class Program {
public static void Main() {
string[] text = new string[] {"dsasaffasfasfafsa", "siuuuuu", "ewqewqeqeqewqeq"};
Console.WriteLine(AllLengthsEqual(text));
}
public static bool AllLengthsEqual(string[] strArr) {
return strArr == null ? true : (strArr.Length < 2 ? true : AllLengthsEqual(strArr, 0));
}
private static bool AllLengthsEqual(string[] strArr, int index) {
return AllLengthsEqual(strArr, index + 1, strArr[index] != null ? strArr[index].Length : -1);
}
private static bool AllLengthsEqual(string[] strArr, int index, int prevLength) {
if (index < strArr.Length) {
int thisLength = strArr[index] != null ? strArr[index].Length : -1;
return (thisLength == prevLength) && AllLengthsEqual(strArr, index + 1, thisLength);
}
else
return true;
}
}

Related

sort files of folder in ascending order in C#

I want to sort the files of folder in the ascending order so that I can combine that files properly but the output I am getting is, 1,10,11 like wise and I want the output as, 1,2,3.. like wise.
I am using this,
DirectoryInfo di = new DirectoryInfo(source_path);
FileInfo[] arrFi = di.GetFiles("*.*");
//arrFi.OrderBy(fi=>fi.LastWriteTime);
Array.Sort(arrFi.OrderBy(fi => fi.LastWriteTime));
It's unclear what is the desired result looks like. If you want to sort files by their last write time a
simple Linq query will do:
var arrFi = new DirectoryInfo(source_path)
.EnumerateFiles("*.*")
.OrderBy(file => file.LastWriteTime)
.ToArray();
If you want to order files by their names in natural order (i.e. "1" < "5" < "9" < "10" < "12" < "100") the
query itself will be as easy as the previous one:
var arrFi = new DirectoryInfo(source_path)
.EnumerateFiles("*.*")
.OrderBy(file => file.Name, new StringNaturalComparer(null))
.ToArray();
But you have to implement the comparer:
public sealed class StringNaturalComparer : IComparer<String> {
private readonly IComparer<string> m_Comparer;
private static List<string> ToChunks(string value) {
List<string> result = new();
StringBuilder sb = null;
bool isDigit = false;
foreach (var c in value) {
if (sb is null) {
sb = new StringBuilder(value.Length);
isDigit = char.IsDigit(c);
sb.Append(c);
}
else if (isDigit != char.IsDigit(c)) {
result.Add(sb.ToString());
sb.Clear();
isDigit = char.IsDigit(c);
}
sb.Append(c);
}
if (sb != null)
result.Add(sb.ToString());
return result;
}
public StringNaturalComparer(IComparer<string> comparer) {
m_Comparer = comparer == null ? StringComparer.Ordinal : comparer;
}
public int Compare(string left, string right) {
if (ReferenceEquals(left, right))
return 0;
else if (left == null)
return -1;
else if (right == null)
return 1;
var lefts = ToChunks(left);
var rights = ToChunks(right);
int result;
for (int i = 0; i < Math.Min(lefts.Count, rights.Count); ++i) {
string leftChunk = lefts[i];
string rightChunk = rights[i];
if (char.IsDigit(leftChunk[0]) && char.IsDigit(rightChunk[0])) {
result = leftChunk.Length.CompareTo(rightChunk.Length);
if (result != 0)
return result;
}
result = m_Comparer.Compare(leftChunk, rightChunk);
if (result != 0)
return result;
}
return lefts.Count.CompareTo(rights.Count);
}
}

TextToSplit does not exist in current context

Am giving to 2 variables the data type as string and integer.
However C# is saying that they don't exist.
Have tried something as object TexttoSplit { get; private set; } but still doesn't run correctly.
Any help would be much appreciated!
private static List<string> SplitTextByLengthEngine(string Texttosplit, int MaxLineLength)
{
List<string> RetVal = new List<string>();
MaxLineLength = Math.Min(MaxLineLength, TexttoSplit.Length);
int LastIndex = TexttoSplit.Substring(0, Math.Min((MaxLineLength + 1), TextToSplit.Length)).LastIndexOf(" ");
if (((TextToSplit.Length <= MaxLineLength)
|| (LastIndex == -1)))
{
RetVal.Add(TexttoSplit.Substring(0, MaxLineLength));
string RemainingText = TexttoSplit.SubString(MaxLineLength, (TextToSplit.Length - MaxLineLength)).Trim();
}
if ((RemainingText.Length > 0))
{
RetVal.AddRange(SplitTextByLengthEngine(RemainingText, MaxLineLength));
}
else
{
// Track backwards to find previous non-space character
int Index = (LastIndex - 1);
while (((Index >= 0)
&& (TextToSplit.SubString(Index, 1) == " ")))
{
Index--;
}
if ((Index >= 0))
{
RetVal.Add(TextToSplit.SubString(0, (Index + 1)));
string RemainingText = TexttoSplit.SubString((Index + 1), (TextToSplit.Length
- (Index + 1))).Trim();
}
if ((RemainingText.Length > 0))
{
RetVal.AddRange(SplitTextByLengthEngine(RemainingText, MaxLineLength));
}
return RetVal;
}
}
The method argument is called Texttosplit
In the method body you refer to TextToSplit
Note the difference in upper/lowercase

XML - System.Xml.XmlException - hexadecimal value 0x06

I get this error. Later I searched and found out the reason of illegal characters in my XML and its solution. But I don't have the access to edit any of these files. My job is to read and fetch the tag value, attribute value and similar stuff. SO I can't replace the binary characters with escapes like '\x01' with &#01. Also I tried to include CheckCharacters =false in XMLreader settings. It doesn't take this. Still it is throwing the same error.
Is it not possible to fix in XMLreader? I read about XMLtextReader. It can skip the exception. But already I have coded for all my features using XMLreader. It would be good if I can find a solution for this. Otherwise I would have to change all my code.
My code:
private void button1_Click(object sender, EventArgs e)
{
int i = 0;
var filenames = System.IO.Directory
.EnumerateFiles(textBox1.Text, "*.xml", System.IO.SearchOption.AllDirectories)
.Select(System.IO.Path.GetFullPath);
foreach (var f in filenames)
{
var resolver = new XmlUrlOverrideResolver();
resolver.DtdFileMap[#"X1.DTD"] = #"\\location\X1.DTD";
resolver.DtdFileMap[#"R2.DTD"] = #"\\location\X2.DTD";
resolver.DtdFileMap[#"R5.DTD"] = #"\\location\R5.DTD";
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.XmlResolver = resolver;
XmlReader doc = XmlReader.Create(f, settings);
while (doc.Read())
{
if ((doc.NodeType == XmlNodeType.Element) && (doc.Name == "ap"))
{
if (doc.HasAttributes)
{
String fin = doc.GetAttribute("ap");
if (fin == "no")
{
String[] array = new String[10000];
array[i] = (f);
File.AppendAllText(#"\\location\NAPP.txt", array[i] + Environment.NewLine);
i++;
}
else
{
String[] abs = new String[10000];
abs[i] = (f);
File.AppendAllText(#"\\location\APP.txt", abs[i] + Environment.NewLine);
i++;
}
}
}
}
}
MessageBox.Show("Done");
}
This is a very simple example of character "filter" that will replae the 0x06 character with a space:
public class MyStreamReader : StreamReader {
public MyStreamReader(string path)
: base(path) {
}
public override int Read(char[] buffer, int index, int count) {
int res = base.Read(buffer, index, count);
for (int i = 0; i < res; i++) {
if (buffer[i] == 0x06) {
buffer[i] = ' ';
}
}
return res;
}
}
You use it this way:
using (var sr = new MyStreamReader(f)) {
var doc = XmlReader.Create(sr, settings);
Note that it's very simple because it's replacing a character (the 0x06) with another character of the same "length" (the space). If you wanted to replace a character with a "sequence" of characters (to escape it), it would get more complex (not impossible, 30 minutes of work difficult)
(I have checked and it seems the XmlTextReader only uses that method and not the Read() method)
As always, when a programmer tells you 30 minutes, it means 0 minutes or 2 hours :-)
This is the "more complex" ReplacingStreamReader:
/// <summary>
/// Only the Read methods are supported!
/// </summary>
public class ReplacingStreamReader : StreamReader
{
public ReplacingStreamReader(string path)
: base(path)
{
}
public Func<char, string> ReplaceWith { get; set; }
protected char[] RemainingChars { get; set; }
protected int RemainingCharsIndex { get; set; }
public override int Read()
{
int ch;
if (RemainingChars != null)
{
ch = RemainingChars[RemainingCharsIndex];
RemainingCharsIndex++;
if (RemainingCharsIndex == RemainingChars.Length)
{
RemainingCharsIndex = 0;
RemainingChars = null;
}
}
else
{
ch = base.Read();
if (ch != -1)
{
string replace = ReplaceWith((char)ch);
if (replace == null)
{
// Do nothing
}
else if (replace.Length == 1)
{
ch = replace[0];
}
else
{
ch = replace[0];
RemainingChars = replace.ToCharArray(1, replace.Length - 1);
RemainingCharsIndex = 0;
}
}
}
return ch;
}
public override int Read(char[] buffer, int index, int count)
{
int res = 0;
// We leave error handling to the StreamReader :-)
// We handle only "working" parameters
if (RemainingChars != null && buffer != null && index >= 0 && count > 0 && index + count <= buffer.Length)
{
int remainingCharsCount = RemainingChars.Length - RemainingCharsIndex;
res = Math.Min(remainingCharsCount, count);
Array.Copy(RemainingChars, RemainingCharsIndex, buffer, index, res);
RemainingCharsIndex += res;
if (RemainingCharsIndex == RemainingChars.Length)
{
RemainingCharsIndex = 0;
RemainingChars = null;
}
if (res == count)
{
return res;
}
index += res;
count -= res;
}
while (true)
{
List<char> sb = null;
int res2 = base.Read(buffer, index, count);
if (res2 == 0 || ReplaceWith == null)
{
return res;
}
int j = 0;
for (int i = 0; i < res2; i++)
{
char ch = buffer[index + i];
string replace = ReplaceWith(ch);
if (sb != null)
{
if (replace == null)
{
sb.Add(ch);
}
else
{
sb.AddRange(replace);
}
}
else if (replace == null)
{
buffer[j] = ch;
j++;
}
else if (replace.Length == 1)
{
buffer[j] = replace[0];
j++;
}
else if (replace.Length == 0)
{
// We do not advance
}
else
{
sb = new List<char>();
sb.AddRange(replace);
}
}
res2 = j;
if (sb != null)
{
int res3 = Math.Min(sb.Count, count - res2);
sb.CopyTo(0, buffer, index + res2, res3);
if (res3 < sb.Count)
{
RemainingChars = new char[sb.Count - res3];
RemainingCharsIndex = 0;
sb.CopyTo(res3, RemainingChars, 0, RemainingChars.Length);
}
res += res3;
}
else
{
res2 = j;
// Can't happen if sb != null (at least a character must
// have been added)
if (res2 == 0)
{
continue;
}
}
res += res2;
return res;
}
}
}
Use it like:
using (var sr = new ReplacingStreamReader(f))
{
sr.ReplaceWith = x =>
{
return x == 0x6 ? " " : null;
// return x == '.' ? " " : null; // Replace all . with
};
var doc = XmlReader.Create(sr, settings);
Be aware that the ReplacingStreamReader doesn't "know" which part of the xml it is modifying, so rarely a "blind" replace is ok :-) Other than this limitation, you can replace any character with any string (null in the ReplaceWith means "keep the current character", equivalent to x.ToString() in the example given. Returning string.Empty is valid, means remove the current character).
The class is quite interesting: it keeps a char[] RemainingChars with the chars that have been read (and filtered by ReplaceWith) but that haven't been returned by a Read() method because the passed buffer was too much small (the ReplaceWith method could "enlarge" the read string, making it too much big for the buffer!). Note that sb is a List<char> instead of a StringBuilder. Probably using one or the other would be nearly equivalent, code-wise.
You could first read the content into a string replace (escape) the content, and then load it into a XmlReader:
foreach (var f in filenames) {
string text;
using (StreamReader s = new StreamReader(f,Encoding.UTF8)) {
text = s.ReadToEnd();
}
text = text.Replace("\x01",#"&#01"); //replace the content
//load some settings
var resolver = new XmlUrlOverrideResolver();
resolver.DtdFileMap[#"X1.DTD"] = #"\\location\X1.DTD";
resolver.DtdFileMap[#"R2.DTD"] = #"\\location\X2.DTD";
resolver.DtdFileMap[#"R5.DTD"] = #"\\location\R5.DTD";
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.XmlResolver = resolver;
XmlReader doc = XmlReader.Create(text, settings);
//perform processing task
//...
}

Check if array is null and has content

I'm in search for some code-improvement. I currently have the following piece of code:
if (pMyDocAction.s_locatie_st != null)
{
String[] myLocaties = Globals.GlobalTools.DeserializeValueToStringArray(pMyDocAction.s_locatie_st);
if (myLocaties != null)
if (myLocaties.Length > 0)
row.Locatie = myLocaties[0];
else
row.Locatie = String.Empty;
else
row.Locatie = String.Empty;
}
else
row.Locatie = String.Empty;
Mylocaties is a Array of String and this cannot change. How can i shorten this piece of code (or how can i combine the != null and .length > 0?
Thnx
You can use conditional operator and write that statement like this:
row.Locatie = (myLocaties != null &&
myLocaties.Length > 0) ? myLocaties[0] : String.Empty
I would suggest you to create a small extension method:
public static class ArrayExtension{
public static bool HasContent<T>(Array<T> array) {
return array != null && array.Length > 0;
}
}
Then you can check :
int[] x = null;
x.HasContent(); // false
string[] strs = new string[] {};
strs.HasContent(); // false
string[] strs2 = new string[] {"foo", "bar" };
strs.HasContent(); // true
This can be extended to simplify your syntax:
public static class ArrayExtension{
public static T FirstValueOrDefault<T>(Array<T> array, T #default) {
if( array != null && array.Length >0 ){
return array[0];
}
else {
return #default;
}
}
}
int[] x = null;
int y = x.FirstValueOrDefault(42); // 42
string[] strs = new string[] {};
string some = strs.FirstValueOrDefault("default"); // default
string[] strs2 = new string[] {"foo", "bar" };
string some2 = strs.FirstValueOrDefault("default"); // foo
Use && operator on two conditions, it will do short-circuit evaluation and if first condition is false, it will not evaluate the second condition.
if (myLocaties != null && myLocaties.Length > 0)
{
row.Locatie = myLocaties[0];
}
else
{
row.Locatie = String.Empty;
}
Since all other answers seem to ignore the if (pMyDocAction.s_locatie_st != null), something like this seems to be the most reusable:
row.Locatie = DeserializeLocation(pMyDocAction.s_locatie_st);
string DeserializeLocation(string locationString)
{
var result = "";
if (!string.IsNullOrEmpty(locationString))
{
String[] deserializedLocations =
Globals.GlobalTools.DeserializeValueToStringArray(locationString);
if (deserializedLocations != null && deserializedLocations.Any())
{
result = deserializedLocations[0];
}
}
return result;
}
You might even consider putting this method in your "GlobalTools" class, so you can call it from anywhere were you need to deserialize a potentially null-bearing serialized location string into a location string.

Function convert Hex String to BitArray C#

I created the following function which will do as requested (convert HEX string to BitArray). I am not sure about the efficiency of the function, but my main problem now is that the Convert.ToInt64 function is endian specific. When this is ported over to alternate chipsets we will get different results (or exceptions). So can anyone think of an alternate way to do this conversion???
public BitArray convertHexToBitArray(string hexData)
{
string binary_values = "";
BitArray binary_array;
if (hexData.Length <= "FFFFFFFFFFFFFFFF".Length) // Max Int64
{
binary_values = Convert.ToString(Convert.ToInt64(hexData, 16), 2);
binary_array = new BitArray(binary_values.Length);
for (int i = 0; i < binary_array.Length; i++)
{
if (binary_values[i] == '0')
{
binary_array[i] = false;
}
else
{
binary_array[i] = true;
}
}
}
}
I removed most of the error / exception handling to keep this to size so plz forgive that.
here is a simple answer, should work with a string of any length:
public static BitArray ConvertHexToBitArray(string hexData)
{
if (hexData == null)
return null; // or do something else, throw, ...
BitArray ba = new BitArray(4 * hexData.Length);
for (int i = 0; i < hexData.Length; i++)
{
byte b = byte.Parse(hexData[i].ToString(), NumberStyles.HexNumber);
for (int j = 0; j < 4; j++)
{
ba.Set(i * 4 + j, (b & (1 << (3 - j))) != 0);
}
}
return ba;
}
Try this:
var int64 = Int64.Parse(hexData, NumberStyles.HexNumber);
var bytes = BitConverter.GetBytes(int64);
var bitArray = new BitArray(bytes);
I haven't tested this (consider it pseduo code), but it would be fast:
public static BitArray ConvertHexToBitArray(string hex)
{
Guard.AssertNotNullOrEmpty(hex, "hex");
Guard.AssertHex(hex, "hex");
var bits = new BitArray(hex.Length * 4);
int pos = 0;
foreach(char c in hex)
{
foreach(bool flag in LookupBits(c))
{
bits.Set(pos, flag);
pos++;
}
}
return bits;
}
private static readonly Dictionary<char, List<bool>> _hexVsBits = CreateHexLookupTable();
private static Dictionary<char, List<bool>> CreateHexLookupTable()
{
var hexVsBits = new Dictionary<char, List<bool>>();
hexVsBits.Add('0', CreateBitsArray(false, false, false, false));
hexVsBits.Add('1', CreateBitsArray(false, false, false, true));
hexVsBits.Add('2', CreateBitsArray(false, false, true, false));
hexVsBits.Add('3', CreateBitsArray(false, false, true, true));
hexVsBits.Add('4', CreateBitsArray(false, true, false, false));
hexVsBits.Add('5', CreateBitsArray(false, true, false, true));
hexVsBits.Add('6', CreateBitsArray(false, true, true, false));
hexVsBits.Add('7', CreateBitsArray(false, true, true, true));
// complete hex table
return hexVsBits;
}
private static List<bool> CreateBitsArray(bool msb, bool msbMinusOne, bool lsbPlusOne, bool lsb)
{
var bits = new List<bool>(4);
bits.Add(msb);
bits.Add(msbMinusOne);
bits.Add(lsbPlusOne);
bits.Add(lsb);
return bits;
}
private static IEnumerable<bool> LookupBits(char hexValue)
{
return _hexVsBits[hexValue];
}
}
And the guards:
public static class Guard
{
public static void AssertHex(string value, string parameterName)
{
foreach(char entry in value)
{
if (!Char.IsNumber(entry))
{
if (entry != 'a' && entry != 'A' && entry != 'b' && entry != 'B'
&& entry != 'c' && entry != 'C' && entry != 'd' && entry != 'D' && entry != 'e' && entry != 'E' && entry != 'f' && entry != 'F')
{
throw new ArgumentException("Not a valid hexidecimal number", parameterName);
}
}
}
}
public static void AssertNotNullOrEmpty(string value, string parameterName)
{
if (string.IsNullOrEmpty(value))
throw new ArgumentNullException(parameterName);
}
}

Categories

Resources