Hoping I can explain this clearly ... I have a collection of variables:
static string sRunnerSetName, sFH, sR1, sH2, sR2, sH3, sR3, sH4, sR4, sH5, sR5 = "";
static int iRunnerSetName, iFH, iR1, iH2, iR2, iH3, iR3, iH4, iR4, iH5, iR5 = 0;
Each of the int variables hold a unique value, which provide the order that the corresponding string variables need to be combined and put into a concatenated string. So iFH holds the sorting/order-number position for where the string sFH will be positioned in the concatenated string.
I'm just stuck with how to use the values in each int to create the order of strings?
As an example -
iFH = 2; i1R = 0; i2R = 1;
sFH = "z"; s1R = "x"; s2R = "y";
Looking to use the values in the integer variables to create the order/position of each string so that the concatenated result of the above would be "xyz".
Create a class holding a string and an int:
class Item
{
public string Description {get;set;}
public int SortOrder {get;set;}
}
Create a list (or another collection, which fits better to your needs) of these items:
List<Item> list = new List<Item>
{
new Item { Description = "Test", SortOrder = 4 },
new Item { Description = "Test2", SortOrder = 3 },
new Item { Description = "sadf", SortOrder = 1 },
new Item { Description = "Example", SortOrder = 2 },
new Item { Description = "something", SortOrder = 5 }
};
You can use LINQ to sort your list:
list = list.OrderBy(x => x.SortOrder).ToList();
You can then output it on console:
Console.WriteLine(string.Join("\n", list.Select(x => x.Description)));
Try it online
You could use arrays here; copy the data into the arrays, then sort them using the index one as the master:
string a = "a", b = "b", c = "c", d = "d";
int ia = 3, ib = 2, ic = 0, id = 1;
string[] sarr = null;
int[] iarr = null;
try
{
// put the data into vectors; we can't talk about variables
// abstractly, but we *can* talk about vectors by position
sarr = ArrayPool<string>.Shared.Rent(4);
iarr = ArrayPool<int>.Shared.Rent(4);
sarr[0] = a;
sarr[1] = b;
sarr[2] = c;
sarr[3] = d;
iarr[0] = ia;
iarr[1] = ib;
iarr[2] = ic;
iarr[3] = id;
var sb = new StringBuilder();
Array.Sort(iarr, sarr, 0, 4);
for (int i = 0; i < 4; i++)
{
sb.Append(sarr[i]);
}
sb.AppendLine();
Console.WriteLine(sb.ToString());
}
finally
{
if (sarr is not null) ArrayPool<string>.Shared.Return(sarr);
if (iarr is not null) ArrayPool<int>.Shared.Return(iarr);
}
Not super efficient, but it would work. However, it is probably better to re-frame the problem; from your example:
iFH = 2; i1R = 0; i2R = 1;
sFH = "z"; s1R = "x"; s2R = "y";
If we instead say:
string[] sarr = { "z", "x", "y"};
and now talk in terms of what tokens you want, by position:
int[] iarr = { 1, 2, 0 };
now you can just use:
foreach (int i in iarr) {
sb.Append(sarr[i]);
}
One possible solution: use a SortedDictionary<int, string> like this:
int iFH = 2, i1R = 0, i2R = 1;
string sFH = "z", s1R = "x", s2R = "y";
var map = new SortedDictionary<int, string>();
map[iFH] = sFH;
map[i1R] = s1R;
map[i2R] = s2R;
var result = string.Join("", map.Values);
If I understand correctly, you mean to use the int values as order number in an array of strings. Since the int values are of type int, you could directly use them as values. For Example, assuming you have an array of strings called stringArray,
stringArray[iFH] = sFH;
Doing this for all the strings you can make an ordered array. To concatenate them all, you can iterate over the array and add them to a seperate string in the following way:
String finalString = "";
for(int i = 0; i < stringArray.Length; i++){
finalString = finalString + stringArray[i];
}
console.WriteLine(finalString);
Splitting the problem into two
Converting an arbitrarily long random list of variables into an
array
Using the array to create a concatenated string
For part 1, create a function that takes params
public static string[] StringList(params object[] stringValues) => stringValues.Cast<string>().ToArray();
public static int[] PositionList(params object[] intValues) => intValues.Cast<int>().ToArray();
For part 2
public static string Join(string[] text, int[] positions)
{
string[] final = new string[text.Length];
for (int i = 0; i < text.Length; i++)
{
final[positions[i]] = text[i];
}
return string.Join("", final);
}
Then run like this:
public static string RunExample()
{
string sFH = "z"; string s1R = "x"; string s2R = "y";
int iFH = 2; int i1R = 0; int i2R = 1;
return Join(StringList(sFH, s1R, s2R), PositionList(iFH, i1R, i2R));
}
Entire example:
public static class Joiner
{
public static string[] StringList(params object[] stringValues) => stringValues.Cast<string>().ToArray();
public static int[] PositionList(params object[] intValues) => intValues.Cast<int>().ToArray();
public static string Join(string[] text, int[] positions)
{
string[] final = new string[text.Length];
for (int i = 0; i < text.Length; i++)
{
final[positions[i]] = text[i];
}
return string.Join("", final);
}
public static string RunExample()
{
string sFH = "z"; string s1R = "x"; string s2R = "y";
int iFH = 2; int i1R = 0; int i2R = 1;
return Join(StringList(sFH, s1R, s2R), PositionList(iFH, i1R, i2R));
}
}
You can add your own code for exception handling (mismatch in array sizes etc).
Related
I'm trying to convert a char array to a string, and put the string in a TextBlock.
The specific line '_textBl.Text = word;' makes my program unable to run, here's the whole code.
public sealed partial class MainPage : Page
{
int _currentIndex;
string _currentWord;
string[] _strArr = { "ant", "bee", "spider", "mosquito" };
int _difficulty = 1;
public MainPage()
{
Random rnd = new Random();
_currentIndex = rnd.Next(0, 5);
foreach (char c in _strArr[_currentIndex])
{
_currentWord = _strArr[_currentIndex];
string _temp = _currentWord;
char[] _wordArr = _currentWord.ToCharArray();
for (int i = 0; i < _wordArr.Length; i++)
{
_wordArr[i] = '_';
}
string word = new string(_wordArr);
_textBl.Text = word;
}
this.InitializeComponent();
}
}
}
You could to insert the spaces in your string with (char)160, I simplified your code like the following.
Please note the _strArr implemented only has 4 items, if you make rnd.Next(0, 5), it will cause access out of range issue.
int _currentIndex;
string _currentWord;
string[] _strArr = { "ant", "bee", "spider", "mosquito" };
int _difficulty = 1;
Random rnd = new Random();
_currentIndex = rnd.Next(0, 4);
foreach (char c in _strArr[_currentIndex])
{
_currentWord = _strArr[_currentIndex];
string rest = string.Empty;
foreach (var item in _currentWord)
{
rest += "_" + (char)160;
}
MyTb.Text = rest;
}
I am currently trying to make a random password generator.
My code works fine if I only pick one type of symbols.
What's the best way to make my code to word for more than one type?
Also what parameters would you add to make the password more secured?
I am thinking of adding an if loop to check if there are more than two same letters, symbols or numbers in a row.
That's how my interface looks like:
and that is my code:
public partial class Form1 : Form
{
// Max number of identical characters in a row
const int Maximum_Identical = 2;
// lower case chars
const string lower_chars = "abcdefghijklmnopqrstuvwxyz";
// capital chars
const string capital_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// numbers
const string numbers = "0123456789";
// symbols
const string symbols = #"!#$%&*#\";
// password lenght
int lenght;
private void button1_Click(object sender, EventArgs e)
{
//use stringbuilder so I can add more chars later
StringBuilder password = new StringBuilder();
//take max lenght from numericUpDown
lenght = Convert.ToInt32(numericUpDown1.Value);
// random instance so I can use Next and don't get loops
Random rdm = new Random();
if (small_letters__Box.Checked)
{
//add a random small character to pass untill it reaches the selected lenght
while (lenght-- > 0 )
{
password.Append(lower_chars[rdm.Next(lower_chars.Length)]);
}
}
if (capital_letters__Box.Checked)
{
//add a random capital character to pass untill it reaches the selected lenght
while (lenght-- > 0)
{
password.Append(capital_chars[rdm.Next(capital_chars.Length)]);
}
}
if (numbers_Box.Checked)
{
//add a random character to pass untill it reaches the selected lenght
while (lenght-- > 0)
{
password.Append(numbers[rdm.Next(numbers.Length)]);
}
}
if (symbols_Box.Checked)
{
//add a random character to pass untill it reaches the selected lenght
while (lenght-- > 0)
{
password.Append(symbols[rdm.Next(symbols.Length)]);
}
}
textBox1.Text = password.ToString();
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
}
}
Your password generation has 2 steps.
Determine the character set
Create a password randomly from the character set of length n
Function 1 creates the character set:
// Make sure you have using System.Linq;
private List<char> GetCharacterSet()
{
IEnumerable<char> returnSet = new char[]{};
if (small_letters__Box.Checked)
{
returnSet = returnSet.Append(lower_chars);
}
if (capital_letters__Box.Checked)
{
returnSet = returnSet.Append(capital_chars);
}
if (numbers_Box.Checked)
{
returnSet = returnSet.Append(numbers);
}
if (symbols_Box.Checked)
{
returnSet = returnSet.Append(symbols);
}
return returnSet.ToList();
}
Function 2 creates a password of given length from your character set
private string GetPassword(int length, List<char> characterSet)
{
if(characterSet.Count < 1)
{
throw new ArgumentException("characterSet contains no items!");
}
if(length < 1)
{
return "";
}
Random rdm = new Random();
StringBuilder password = new StringBuilder();
for(int i = 0; i < length; i++){
int charIndex = rdm.Next(0, characterSet.Count)
password.Append(characterSet[charIndex]);
}
return password.ToString();
}
Then simply rig your button click event handler to call these functions and display the resulting password.
below code is my already written code which I wrote more than a couple of years ago and I still use it in my many of my projects where needed, it covers all you are in need of
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading;
public static class ArrayExtentions
{
public static object[] Shuffle(this object[] array)
{
var alreadySwaped = new HashSet<Tuple<int, int>>();
var rndLoopCount = RandomUtils.GetRandom(Convert.ToInt32(array.Length / 4), Convert.ToInt32((array.Length / 2) + 1));
for (var i = 0; i <= rndLoopCount; i++)
{
int rndIndex1 = 0, rndIndex2 = 0;
do
{
rndIndex1 = RandomUtils.GetRandom(0, array.Length);
rndIndex2 = RandomUtils.GetRandom(0, array.Length);
} while (alreadySwaped.Contains(new Tuple<int, int>(rndIndex1, rndIndex2)));
alreadySwaped.Add(new Tuple<int, int>(rndIndex1, rndIndex2));
var swappingItem = array[rndIndex1];
array[rndIndex1] = array[rndIndex2];
array[rndIndex2] = swappingItem;
}
return array;
}
}
public class RandomUtils
{
private static readonly ThreadLocal<Random> RndLocal = new ThreadLocal<Random>(() => new Random(GetUniqueSeed()));
private static int GetUniqueSeed()
{
long next, current;
var guid = Guid.NewGuid().ToByteArray();
var seed = BitConverter.ToInt64(guid, 0);
do
{
current = Interlocked.Read(ref seed);
next = current * BitConverter.ToInt64(guid, 3);
} while (Interlocked.CompareExchange(ref seed, next, current) != current);
return (int)next ^ Environment.TickCount;
}
public static int GetRandom(int min, int max)
{
Contract.Assert(max >= min);
return RndLocal.Value.Next(min, max);
}
public static int GetRandom(int max)
{
return RndLocal.Value.Next(max);
}
public static double GetRandom()
{
return RndLocal.Value.NextDouble();
}
}
public class StringUtility
{
private const string UpperAlpha = "ABCDEFGHIJKLMNOPQRSTUWXYZ";
private const string LowerAlpha = "abcdefghijklmnopqrstuwxyz";
private const string Numbers = "0123456789";
private const string SpecialChars = "~!##$%^&*()_-+=.?";
private static string CreateSourceString(bool includeLowerCase, bool includeUpperCase, bool includenumbers, bool includeSpChars)
{
Contract.Assert(includeLowerCase || includeUpperCase || includenumbers || includeSpChars);
var sb = new StringBuilder();
if (includeLowerCase) sb.Append(LowerAlpha);
if (includeUpperCase) sb.Append(UpperAlpha);
if (includenumbers) sb.Append(Numbers);
if (includeSpChars) sb.Append(SpecialChars);
return sb.ToString();
}
private static string GenerateString(string sourceString, int length = 6)
{
var rndString = Shuffle(sourceString);
var builder = new StringBuilder();
for (var i = 0; i < length; i++)
builder.Append(rndString[RandomUtils.GetRandom(0, rndString.Length)]);
return builder.ToString();
}
public static string GenerateRandomString(int length = 6,
bool includenumbers = false,
bool includeSpChars = false)
{
var sourceStr = CreateSourceString(true, true, includenumbers, includeSpChars);
return GenerateString(sourceStr, length);
}
public static string GenerateRandomString(int minLength,
int maxLength,
bool includenumbers = false,
bool includeSpChars = false)
{
if (maxLength < minLength) maxLength = minLength;
var len = RandomUtils.GetRandom(minLength, maxLength + 1);
return GenerateRandomString(len, includenumbers, includeSpChars);
}
public static string Shuffle(string str)
{
var alreadySwaped = new HashSet<Tuple<int, int>>();
var rndLoopCount = RandomUtils.GetRandom(Convert.ToInt32(str.Length / 4), Convert.ToInt32((str.Length / 2) + 1));
var strArray = str.ToArray();
for (var i = 0; i <= rndLoopCount; i++)
{
int rndIndex1 = 0, rndIndex2 = 0;
do
{
rndIndex1 = RandomUtils.GetRandom(0, str.Length);
rndIndex2 = RandomUtils.GetRandom(0, str.Length);
} while (alreadySwaped.Contains(new Tuple<int, int>(rndIndex1, rndIndex2)));
alreadySwaped.Add(new Tuple<int, int>(rndIndex1, rndIndex2));
var swappingChar = strArray[rndIndex1];
strArray[rndIndex1] = strArray[rndIndex2];
strArray[rndIndex2] = swappingChar;
}
return new string(strArray);
}
public static string GeneratePassword(PasswordComplexity complexityLevel)
{
switch (complexityLevel)
{
case PasswordComplexity.Simple: return GenerateSimplePassword();
case PasswordComplexity.Medium: return GenerateMediumPassword();
case PasswordComplexity.Strong: return GenerateStrongPassword();
case PasswordComplexity.Stronger: return GenerateStrongerPassword();
}
return null;
}
private static string GenerateSimplePassword()
{
return GenerateRandomString(6, 9);
}
private static string GenerateMediumPassword()
{
var passLen = RandomUtils.GetRandom(6, 10);
var numCount = RandomUtils.GetRandom(1, 3);
var alphaStr = GenerateRandomString(passLen - numCount);
var numStr = GenerateString(Numbers, numCount);
var pass = alphaStr + numStr;
return Shuffle(pass);
}
private static string GenerateStrongPassword()
{
var lowerCharCount = RandomUtils.GetRandom(2, 5);
var upperCharCount = RandomUtils.GetRandom(2, 5);
var numCount = RandomUtils.GetRandom(2, 4);
var spCharCount = RandomUtils.GetRandom(2, 4);
var lowerAlphaStr = GenerateString(LowerAlpha, lowerCharCount);
var upperAlphaStr = GenerateString(UpperAlpha, upperCharCount);
var spCharStr = GenerateString(SpecialChars, spCharCount);
var numStr = GenerateString(Numbers, numCount);
var pass = lowerAlphaStr + upperAlphaStr + spCharStr + numStr;
return Shuffle(pass);
}
private static string GenerateStrongerPassword()
{
var lowerCharCount = RandomUtils.GetRandom(5, 12);
var upperCharCount = RandomUtils.GetRandom(4, 8);
var numCount = RandomUtils.GetRandom(4, 6);
var spCharCount = RandomUtils.GetRandom(4, 6);
var lowerAlphaStr = GenerateString(LowerAlpha, lowerCharCount);
var upperAlphaStr = GenerateString(UpperAlpha, upperCharCount);
var spCharStr = GenerateString(SpecialChars, spCharCount);
var numStr = GenerateString(Numbers, numCount);
var pass = lowerAlphaStr + upperAlphaStr + spCharStr + numStr;
return Shuffle(Shuffle(pass));
}
public enum PasswordComplexity
{
Simple, Medium, Strong, Stronger
}
}
I write this code for you. You can just copy and use it. All of my code is just a method that you can pass appropriate arguments and it gives you back a completely randomized password. I test it several times before answering your question, It works well.
private string GeneratePassword(bool useCapitalLetters, bool useSmallLetters, bool useNumbers, bool useSymbols, int passLenght)
{
Random random = new Random();
StringBuilder password = new StringBuilder(string.Empty);
//This for loop is for selecting password chars in order
for (int i = 0;;)
{
if (useCapitalLetters)
{
password.Append((char)random.Next(65, 91)); //Capital letters
++i; if (i >= passLenght) break;
}
if (useSmallLetters)
{
password.Append((char)random.Next(97, 122)); //Small letters
++i; if (i >= passLenght) break;
}
if (useNumbers)
{
password.Append((char)random.Next(48, 57)); //Number letters
++i; if (i >= passLenght) break;
}
if (useSymbols)
{
password.Append((char)random.Next(35, 38)); //Symbol letters
++i; if (i >= passLenght) break;
}
}
//This for loop is for disordering password characters
for (int i = 0; i < password.Length; ++i)
{
int randomIndex1 = random.Next(password.Length);
int randomIndex2 = random.Next(password.Length);
char temp = password[randomIndex1];
password[randomIndex1] = password[randomIndex2];
password[randomIndex2] = temp;
}
return password.ToString();
}
an answer with complete randomize char and using the max repeat of char, i have added a shuffle string function:
const int Maximum_Identical = 2; // Max number of identical characters in a row
const string lower_chars = "abcdefghijklmnopqrstuvwxyz"; // lower case chars
const string capital_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //capital chars
const string numbers = "0123456789"; //numbers
const string symbols = #"!#$%&*#\"; //symbols
int lenght = 6; //
bool lowercase = true, capital=true, num=true, sym=true;
List<char[]> PasswordSet = new List<char[]>();
List<char[]> charSet = new List<char[]>();
List<int[]> countSet = new List<int[]>();
if (lowercase) charSet.Add(lower_chars.ToArray());
if (capital) charSet.Add(capital_chars.ToArray());
if (num) charSet.Add(numbers.ToArray());
if (sym) charSet.Add(symbols.ToArray());
foreach(var c in charSet)
countSet.Add(new int[c.Length]);
Random rdm = new Random();
//we create alist with each type with a length char (max repeat char included)
for(int i = 0; i < charSet.Count;i++)
{
var lng = 1;
var p0 = "";
while (true)
{
var ind = rdm.Next(0, charSet[i].Length);
if (countSet[i][ind] < Maximum_Identical )
{
countSet[i][ind] += 1;
lng++;
p0 += charSet[i][ind];
}
if (lng == lenght) break;
}
PasswordSet.Add(p0.ToArray());
}
//generate a password with the desired length with at less one char in desired type,
//and we choose randomly in desired type to complete the length of password
var password = "";
for(int i = 0; i < lenght; i++)
{
char p;
if (i < PasswordSet.Count)
{
int id;
do
{
id = rdm.Next(0, PasswordSet[i].Length);
p = PasswordSet[i][id];
} while (p == '\0');
password += p;
PasswordSet[i][id] = '\0';
}
else
{
int id0;
int id1;
do
{
id0 = rdm.Next(0, PasswordSet.Count);
id1 = rdm.Next(0, PasswordSet[id0].Length);
p = PasswordSet[id0][id1];
} while (p == '\0');
password += p;
PasswordSet[id0][id1] = '\0';
}
}
//you could shuffle the final password
password = Shuffle.StringMixer(password);
shuffle string function:
static class Shuffle
{
static System.Random rnd = new System.Random();
static void Fisher_Yates(int[] array)
{
int arraysize = array.Length;
int random;
int temp;
for (int i = 0; i < arraysize; i++)
{
random = i + (int)(rnd.NextDouble() * (arraysize - i));
temp = array[random];
array[random] = array[i];
array[i] = temp;
}
}
public static string StringMixer(string s)
{
string output = "";
int arraysize = s.Length;
int[] randomArray = new int[arraysize];
for (int i = 0; i < arraysize; i++)
{
randomArray[i] = i;
}
Fisher_Yates(randomArray);
for (int i = 0; i < arraysize; i++)
{
output += s[randomArray[i]];
}
return output;
}
}
There you go :
string[] charList =
{
"abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"0123456789",
"#\"!#$%&*#\\"
};
int desiredPasswordLength = 12;
var randomNumberGenerator = new Random();
string generatedPassword = "";
for (int i = randomNumberGenerator.Next() % 4; desiredPasswordLength > 0; i = (i+1) % 4)
{
var takeRandomChars = randomNumberGenerator.Next() % 3;
for (int j = 0; j < takeRandomChars; j++)
{
var randomChar = randomNumberGenerator.Next() % charList[i].Length;
char selectedChar = charList[i][randomChar % charList[i].Length];
generatedPassword = string.Join("", generatedPassword, selectedChar);
}
desiredPasswordLength -= takeRandomChars;
}
Console.WriteLine("Generated password: {0}",generatedPassword);
private static string GeneratorPassword(UInt16 length = 8)
{
const string chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0";
System.Text.StringBuilder sb = new System.Text.StringBuilder();
Random rnd = new Random();
System.Threading.Thread.Sleep(2);
for (int i = 0; i < length; i++)
{
int index = 0;
if (i % 3 == 0)
{
index = rnd.Next(0, 10);
}
else if (i % 3 == 1)
{
index = rnd.Next(10, 36);
}
else
{
index = rnd.Next(36, 62);
}
sb.Insert(rnd.Next(0, sb.Length), chars[index].ToString());
}
return sb.ToString();
}
static void Main(string[] args)
{
for (int j= 0; j < 100; j++)
{
Console.WriteLine( GeneratorPassword());
}
Console.ReadLine();
}
I'm trying to sort a lists of alphanumeric values , in other words a list that contains numbers and strings
Example : BOB10, BOT20, ETC...
List<Object> myList = _items.OrderBy(x => x.FirstName).ToList();
_items= new List<Object>(myList);
But still the output is : BOT20 , BOB10
what is wrong?
First :
Try the alphanumeric algorithm approach ,
First implement the algorithm in a new class, than do this :
List<Object> yourList = new List < Object >(thePreviousList.OrderBy(x => x.FirstName, new AlphanumComparatorFast()).ToList())
As it was explained here :
http://www.dotnetperls.com/alphanumeric-sorting
Implement the algorithm AlphanumComparatorFast by creating a new class , than just call it
Edited :
The alpha algo below :
Public class AlphanumComparatorFast : IComparer
{
public int Compare(object x, object y)
{
string s1 = x as string;
if (s1 == null)
{
return 0;
}
string s2 = y as string;
if (s2 == null)
{
return 0;
}
int len1 = s1.Length;
int len2 = s2.Length;
int marker1 = 0;
int marker2 = 0;
// Walk through two the strings with two markers.
while (marker1 < len1 && marker2 < len2)
{
char ch1 = s1[marker1];
char ch2 = s2[marker2];
// Some buffers we can build up characters in for each chunk.
char[] space1 = new char[len1];
int loc1 = 0;
char[] space2 = new char[len2];
int loc2 = 0;
// Walk through all following characters that are digits or
// characters in BOTH strings starting at the appropriate marker.
// Collect char arrays.
do
{
space1[loc1++] = ch1;
marker1++;
if (marker1 < len1)
{
ch1 = s1[marker1];
}
else
{
break;
}
} while (char.IsDigit(ch1) == char.IsDigit(space1[0]));
do
{
space2[loc2++] = ch2;
marker2++;
if (marker2 < len2)
{
ch2 = s2[marker2];
}
else
{
break;
}
} while (char.IsDigit(ch2) == char.IsDigit(space2[0]));
// If we have collected numbers, compare them numerically.
// Otherwise, if we have strings, compare them alphabetically.
string str1 = new string(space1);
string str2 = new string(space2);
int result;
if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
{
int thisNumericChunk = int.Parse(str1);
int thatNumericChunk = int.Parse(str2);
result = thisNumericChunk.CompareTo(thatNumericChunk);
}
else
{
result = str1.CompareTo(str2);
}
if (result != 0)
{
return result;
}
}
return len1 - len2;
}
}
Why not use List.Sort() instead of OrderBy?
using System;
using System.Collections.Generic;
namespace Test {
static class Program {
static void Main() {
List<string> list = new List<string>() {"BOT20", "BOB10", "BUG40", "BAG90"};
list.Sort();
foreach(var el in list) {
Console.Write(el + ">");
}
}
}
}
Outputs: BAG90>BOB10>BOT20>BUG40>
I have a 2D array of objects called 'value'. I want to convert it to a 2D string array. How do I do this?
object value; //This is a 2D array of objects
string prop[,]; //This is a 2D string
If possible I would also like to know if I can convert the object to
List<List<string>>
directly.
Is this what you are looking for?
string[,] prop; //This is a 2D string
List<List<string>> mysteryList;
if (value is object[,])
{
object[,] objArray = (object[,])value;
// Get upper bounds for the array
int bound0 = objArray.GetUpperBound(0);//index of last element for the given dimension
int bound1 = objArray.GetUpperBound(1);
prop = new string[bound0 + 1, bound1 + 1];
mysteryList = new List<List<string>>();
for (int i = 0; i <= bound0; i++)
{
var temp = new List<string>();
for (int j = 0; j <= bound1; j++)
{
prop[i, j] = objArray[i, j].ToString();//Do null check and assign
temp.Add(prop[i, j]);
}
mysteryList.Add(temp);
}
}
To answer your first question you can achieve the conversion to a 2D string array with this:
List<string[]> objectValues = new List<string[]>
{
new[] { "1", "2", "3" },
new[] { "A", "B", "C" },
};
string[,] prop = ConvertObjectListArray(objectValues );
public T[,] ConvertObjectListArray<T>(IList<T[]> objectList)
{
int Length2 = objectList[0].Length;
T[,] ret = new T[objectList.Count, Length2];
for (int i = 0; i < objectList.Count; i++)
{
var array = objectList[i];
if (array.Length != Length2)
{
throw new ArgumentException
("All arrays must be the same length");
}
for (int i2 = 0; i2 < Length2; i2++)
{
ret[i, i2] = array[i2];
}
}
return ret;
}
I have an array that contains integers
1,1,2,1,1,2,2,2,3,3,3,2,4,4,4,4
I want to be able to replace elements that don't complete the repeated order of the sequence so from the example above it would be like
1,1,1,1,1,2,2,2,3,3,3,3,4,4,4,4.
I have tried playing around with a few ugly sprawling functions but I am like looping through but it was all in vein so am.
wondering if there is a neat LINQ- way to do it.
Any suggestions?
It would be hard if not impossible to implement this in just only LINQ. You would have to implement the following method if you would like to have functionallity like the one you described:
using System;
namespace LinqSequence
{
class Program
{
static void Main(string[] args)
{
var arr = new int[]
{
1,1,2,2,2,1,2,3,3,3,2,4,4,4,5,5,4,4
};
var newArr = SequenceReplace(arr);
Console.WriteLine(String.Join(", ",newArr));
//OUT: 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5
}
static int[] SequenceReplace(int[] arr)
{
int length = arr.Length;
var newArr = new int[length];
int previous = 0;
for (int i = 0; i < length; i++)
{
if (newArr[previous] > arr[i])
{
newArr[i] = newArr[previous];
}
else
{
newArr[i] = arr[i];
}
previous = i;
}
return newArr;
}
}
}
EDIT:
The previous program was not correct because it didn't look at both adjectant fields. So the program didn't work for the test case in your question. So this is the new answer. It looks at both adjectant fields and if current is diffrent than both it replaces current with the one on the left. Also it takes care of edge cases. If the length is less than 2 it just returns that array, if length is 2 it returns array with 2 element 0's. If there is no next element it replaces that element with the previous one.
using System;
namespace LinqSequence
{
class Program
{
static void Main(string[] args)
{
var arr1 = new int[]
{
1,1,2,1,1,2,2,2,3,3,3,2,4,4,4,4
};
var newArr1 = SequenceReplace(arr1);
Console.WriteLine(String.Join(",",newArr1));
//OUT: 1,1,1,1,1,2,2,2,3,3,3,3,4,4,4,4
var arr2 = new int[]
{
1,1,2,2,2,1,2,3,3,3,2,4,4,4,5,5,4,4
};
var newArr2 = SequenceReplace(arr2);
Console.WriteLine(String.Join(",",newArr2));
//OUT: 1,1,2,2,2,2,2,3,3,3,3,4,4,4,5,5,4,4
}
static int[] SequenceReplace(int[] arr)
{
int length = arr.Length;
if (length == 2) return new int[] { arr[0], arr[0] };
else if (length < 2) return arr;
var newArr = new int[length];
newArr[0] = arr[0];
int previous = 0, next = 2;
for (int i = 1; i < length; i++)
{
if ((next < length &&
newArr[previous] != arr[i] &&
arr[next] != arr[i]) ||
next >= length)
{
newArr[i] = newArr[previous];
}
else
{
newArr[i] = arr[i];
}
previous++;
next++;
}
return newArr;
}
}
}
Here's ideone.
Just use orderBy func like this:
List<int> list = new List<int>() { //your data };
list = list.OrderBy(i=> i);
Use sort and regex like this
static void Main(string[] args)
{
string input = "00H1,00H1,00H2,00H1,00H1,00H2,00H2,00H2,00H3,00H3,00H2,00H3";
List<string> array = input.Split(new char[] { ',' }).ToList();
array.Sort((x,y) => GetSuffix(x).CompareTo(GetSuffix(y)));
string output = string.Join(",",array);
}
static int GetSuffix(string input)
{
string pattern = "H(?'suffix'\\d*)";
Match match = Regex.Match(input, pattern);
return int.Parse(match.Groups["suffix"].Value);
}
Here is Linq solution
static void Main(string[] args)
{
string input = "00H1,00H1,00H2,00H1,00H1,00H2,00H2,00H2,00H3,00H3,00H2,00H3";
List<string> array = input.Split(new char[] { ',' }).ToList();
array = array.Select(x => new
{
suffix = GetSuffix(x),
item = x
}).OrderBy(x => x.suffix).Select(x => x.item).ToList();
string output = string.Join(",",array);
}
static int GetSuffix(string input)
{
string pattern = "H(?'suffix'\\d*)";
Match match = Regex.Match(input, pattern);
return int.Parse(match.Groups["suffix"].Value);
}