create array of string builder instead of string - c#

I am creating an application in window application using c#. I have a string array,and its value will be updated in each timer tick event. later on ,i have to convert this array into object array. I know, if we are modifying string many times,it can be time consuming to create new string objects.so i want to use stringBuilder.
let say, in timer tick event:
for (int i = 0; i < 10; i++)
{
n[i] = i.ToString();
}
where n is the string array and i want to use stringbuilder instead of array.
is it possible? how do i do this? how do i convert stringBuilder type to object type?

You do not need a StringBuilder here. A StringBuilder is only called for when processing (usually: concatenating) a single string many times. You have many small and unrelated strings.
What you probably want is to replace the array string[] with a List<string>.

You can keep your array of strings and use a StringBuilder in the loop.
var myValues = new String[100];
void tick() {
var sb = new StringBuilder();
for (int i = 0; i < 10; i++){
sb.append(i.ToString());
}
myValues.add(sb.ToString());
}
This adds all values in the range of 0 to 10 to one string. I don't know why you'd need this, so if you want to do something different you should clarify.

You can do something like this
StringBuilder obj=new StringBuilder();
for (int i = 0; i < 10; i++)
{
obj.append(i.ToString());
}

Here is another approach that does not need to use an array or StringBuilder and which should be efficient enough if the sequence is not too large:
string nums = String.Join("", Enumerable.Range(0, 10));
However, string.Join is really efficient if the input is already an array. In this case it might really be more efficient to use a StringBuilder:
string nums = Enumerable.Range(0, 10)
.Aggregate(new StringBuilder(), (a, b) => a.Append(b))
.ToString();

I would suggest you to use code something like :
class Program
{
static void Main(string[] args)
{
var dic = new Dictionary<int, StringBuilder>();
//Initialize dictionary
for (int i = 0; i < 10; i++)
{
dic.Add(i, new StringBuilder());
}
TimerElapsed(dic);
TimerElapsed(dic);
Process(dic.Values.ToArray());
}
public static void Process(object[] objects)
{
//Do your processing
}
public static void TimerElapsed(IDictionary<int, StringBuilder> dic)
{
for (int i = 0; i < 10; i++)
{
dic[i].Append(i.ToString());
}
}
}
Such code will give you benefits of collection and flexibility (for eg: you could convert to array easily)

Related

How to randomize the word that been get on the textfile

I want to ask if how can I randomize a word that I've get from the textfile data I made.
I already have the word actually from the textfile and stored into an array of character.
Here's what I have so far
I created a method called Shuffle
void Shuffle(string[] chArr)
{
//Shuffle
for (int i = 0; i < chArr.Length; i++)
{
string tmp = chArr[i].ToString();
int r = Random.Range(i, chArr.Length);
chArr[i] = chArr[r];
chArr[r] = tmp;
}
Debug.Log(chArr);
}
and use it like this
string temp = textArray[rowsToReadFrom[0]];
temp = System.Text.RegularExpressions.Regex.Replace(temp, #"\s", "");
char[] chArr = temp.ToCharArray();
string s = chArr.ToString();
string[] ss = new string[] { s };
Shuffle(ss);
foreach (char c in chArr)
{
testObject clone = Instantiate(prefab.gameObject).GetComponent<testObject>();
clone.transform.SetParent(container);
charObjects.Add(clone.Init(c));
//Debug.Log(c);
}
It still doesn't randomize that word I get from the textfile data.
EDITTED
So far here's what I did
string temp = textArray[rowsToReadFrom[0]];
temp = System.Text.RegularExpressions.Regex.Replace(temp, #"\s", "");
char[] chArr = temp.ToCharArray();
string charResult = "";
for(int i = 0; i < chArr.Length; i++)
{
int ran = Random.Range(0, chArr.Length);
charResult += chArr[ran];
}
Debug.Log(charResult);
foreach (char c in charResult)
{
testObject clone = Instantiate(prefab.gameObject).GetComponent<testObject>();
clone.transform.SetParent(container);
charObjects.Add(clone.Init(c));
//Debug.Log(c);
}
But instead of giving me for example the word "Abandon" it would give me sometimes a randomize word "aaaabn" could someone help me out why?
I will be using Fisher–Yates_shuffle
public static string Shuffle(string str)
{
System.Random random = new System.Random();
var array = str.ToCharArray();
for (int i = 0; i < array.Length; i++)
{
int j = random.Next(i, array.Length);
char temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return String.Join("", array);
}
and to use it simply do
var f = "hello";
Console.WriteLine(Shuffle(f));
Your code is just getting random letters from that word but does not exclude duplicate. What you want instead is randomize the array of chars and convert it back to a string
System.Random rnd = new System.Random();
Char[] randomCharArray = chArr.OrderBy(x => rnd.Next()).ToArray();
string charResult = randomCharArray.ToString();
Unity has its own implementation of Random so be sure you use System.Random
it's most easier if you use a list (let call it initial list), (it may have some performance overheat do to shifts on remove, but i'm wonder if using a linked list would solve that...
Here what you can do if you do as i said:
Fill the list, with your words, or char, or any data which you want to randomize
Create another list or array to store randomized data in (result)
create a while loop, and check while, your initial list Has Item (count > 0)
use Random, and performe rand.Next(0, initialList.Count)
take the item within the index of random number and append it to the result list, (or replace free slot if you are using array)
List<string> initial = new List<string>();
initial.AddRange(data);
Random rand = new Random();
List<string> result = new List<string>();
while (initial.Count > 0) // LINQ: initial.Any()
{
int index = rand.Next(0, initial.Count);
result.Add(initial[index]);
initial.RemoveAt(index);
}
return result;

C# - Code optimization to get all substrings from a string

I was working on a code snippet to get all substrings from a given string.
Here is the code that I use
var stringList = new List<string>();
for (int length = 1; length < mainString.Length; length++)
{
for (int start = 0; start <= mainString.Length - length; start++)
{
var substring = mainString.Substring(start, length);
stringList.Add(substring);
}
}
It looks not so great to me, with two for loops. Is there any other way that I can achieve this with better time complexity.
I am stuck on the point that, for getting a substring, I will surely need two loops. Is there any other way I can look into ?
The number of substrings in a string is O(n^2), so one loop inside another is the best you can do. You are correct in your code structure.
Here's how I would've phrased your code:
void Main()
{
var stringList = new List<string>();
string s = "1234";
for (int i=0; i <s.Length; i++)
for (int j=i; j < s.Length; j++)
stringList.Add(s.Substring(i,j-i+1));
}
You do need 2 for loops
Demo here
var input = "asd sdf dfg";
var stringList = new List<string>();
for (int i = 0; i < input.Length; i++)
{
for (int j = i; j < input.Length; j++)
{
var substring = input.Substring(i, j-i+1);
stringList.Add(substring);
}
}
foreach(var item in stringList)
{
Console.WriteLine(item);
}
Update
You cannot improve on the iterations.
However you can improve performance, by using fixed arrays and pointers
In some cases you can significantly increase execution speed by reducing object allocations. In this case by using a single char[] and ArraySegment<of char> to process substrings. This will also lead to use of less address space and decrease in garbage collector load.
Relevant excerpt from Using the StringBuilder Class in .NET page on Microsoft Docs:
The String object is immutable. Every time you use one of the methods in the System.String class, you create a new string object in memory, which requires a new allocation of space for that new object. In situations where you need to perform repeated modifications to a string, the overhead associated with creating a new String object can be costly.
Example implementation:
static List<ArraySegment<char>> SubstringsOf(char[] value)
{
var substrings = new List<ArraySegment<char>>(capacity: value.Length * (value.Length + 1) / 2 - 1);
for (int length = 1; length < value.Length; length++)
for (int start = 0; start <= value.Length - length; start++)
substrings.Add(new ArraySegment<char>(value, start, length));
return substrings;
}
For more information check Fundamentals of Garbage Collection page on Microsoft Docs, what is the use of ArraySegment class? discussion on StackOverflow, ArraySegment<T> Structure page on MSDN and List<T>.Capacity page on MSDN.
Well, O(n**2) time complexity is inevitable, however you can try impove space consumption. In many cases, you don't want all the substrings being materialized, say, as a List<string>:
public static IEnumerable<string> AllSubstrings(string value) {
if (value == null)
yield break; // Or throw ArgumentNullException
for (int length = 1; length < value.Length; ++length)
for (int start = 0; start <= value.Length - length; ++start)
yield return value.Substring(start, length);
}
For instance, let's count all substrings in "abracadabra" which start from a and longer than 3 characters. Please, notice that all we have to do is to loop over susbstrings without saving them into a list:
int count = AllSubstrings("abracadabra")
.Count(item => item.StartsWith("a") && item.Length > 3);
If for any reason you want a List<string>, just add .ToList():
var stringList = AllSubstrings(mainString).ToList();

Adding elements to a C# array

I would like to programmatically add or remove some elements to a string array in C#, but still keeping the items I had before, a bit like the VB function ReDim Preserve.
The obvious suggestion would be to use a List<string> instead, which you will have already read from the other answers. This is definitely the best way in a real development scenario.
Of course, I want to make things more interesting (my day that is), so I will answer your question directly.
Here are a couple of functions that will Add and Remove elements from a string[]...
string[] Add(string[] array, string newValue){
int newLength = array.Length + 1;
string[] result = new string[newLength];
for(int i = 0; i < array.Length; i++)
result[i] = array[i];
result[newLength -1] = newValue;
return result;
}
string[] RemoveAt(string[] array, int index){
int newLength = array.Length - 1;
if(newLength < 1)
{
return array;//probably want to do some better logic for removing the last element
}
//this would also be a good time to check for "index out of bounds" and throw an exception or handle some other way
string[] result = new string[newLength];
int newCounter = 0;
for(int i = 0; i < array.Length; i++)
{
if(i == index)//it is assumed at this point i will match index once only
{
continue;
}
result[newCounter] = array[i];
newCounter++;
}
return result;
}
If you really won't (or can't) use a generic collection instead of your array, Array.Resize is c#'s version of redim preserve:
var oldA = new [] {1,2,3,4};
Array.Resize(ref oldA,10);
foreach(var i in oldA) Console.WriteLine(i); //1 2 3 4 0 0 0 0 0 0
Don't use an array - use a generic List<T> which allows you to add items dynamically.
If this is not an option, you can use Array.Copy or Array.CopyTo to copy the array into a larger array.
Since arrays implement IEnumerable<T> you can use Concat:
string[] strArr = { "foo", "bar" };
strArr = strArr.Concat(new string[] { "something", "new" });
Or what would be more appropriate would be to use a collection type that supports inline manipulation.
Use List<string> instead of string[].
List allows you to add and remove items with good performance.
What's abaut this one:
List<int> tmpList = intArry.ToList();
tmpList.Add(anyInt);
intArry = tmpList.ToArray();
One liner:
string[] items = new string[] { "a", "b" };
// this adds "c" to the string array:
items = new List<string>(items) { "c" }.ToArray();
You should take a look at the List object. Lists tend to be better at changing dynamically like you want. Arrays not so much...
You can use a generic collection, like List<>
List<string> list = new List<string>();
// add
list.Add("element");
// remove
list.Remove("element");
You can use this snippet:
static void Main(string[] args)
{
Console.WriteLine("Enter number:");
int fnum = 0;
bool chek = Int32.TryParse(Console.ReadLine(),out fnum);
Console.WriteLine("Enter number:");
int snum = 0;
chek = Int32.TryParse(Console.ReadLine(),out snum);
Console.WriteLine("Enter number:");
int thnum = 0;
chek = Int32.TryParse(Console.ReadLine(),out thnum);
int[] arr = AddToArr(fnum,snum,thnum);
IOrderedEnumerable<int> oarr = arr.OrderBy(delegate(int s)
{
return s;
});
Console.WriteLine("Here your result:");
oarr.ToList().FindAll(delegate(int num) {
Console.WriteLine(num);
return num > 0;
});
}
public static int[] AddToArr(params int[] arr) {
return arr;
}
I hope this will help to you, just change the type

How to read values from the ArrayList of Structures?

I am using the following code in C#. I am adding the values into the arraylist by using index. Now I want to read the values from the arraylist by using the index only. In the following example I am simply reading all the values from the arrylist but I want to read the values from the arrylist based on index( for e.g Customer_Details[i]) for each element at index i.
public struct Cust_Info
{
public String Client_Key;
public String Registration_Key;
public int Standard;
public Cust_Info(String C_Key, String Reg_Key, int Std)
{
Client_Key = C_Key;
Registration_Key = Reg_Key;
Standard = Std;
}
}
private void Form1_Load(object sender, EventArgs e)
{
ArrayList Customer_Details = new ArrayList();
for (int i = 0; i < 1; i++)
{
Customer_Details.Insert(i, new Cust_Info("A", "B", 1));
}
//for (int i = 0; i < 1; i++)
//{
Customer_Details.Insert(1, new Cust_Info("C", "D", 2));
for (int i = 0; i < 1; i++)
{
ArrayList obj=new ArrayList();
//((ArrayListOFStructures.Form1.Cust_Info)((new System.Collections.ArrayList.ArrayListDebugView(Customer_Details)).Items[0])).Client_Key
//obj = (ArrayList)Customer_Details[i];
foreach (Cust_Info temp in Customer_Details)
{
//comboBox1.Items.Add(Customer_Details[0].ToString());
comboBox1.Items.Add(temp.Client_Key);
comboBox1.Items.Add(temp.Registration_Key);
comboBox1.Items.Add(temp.Standard);
}
}
}
In the above code i want to make the use the structure only. How can I read the values from the arrylist based on index. Can you please provide me any code or link through which I can resolve the above issue ?
I'm confused; you can get an item out of an ArrayList by index simply by:
Cust_Info cust = (CustInfo)theList[index];
However, ArrayList is pretty rare in anything >= .NET 2.0, a List<Cust_Info> would make this much easier. Also, Cust_Info looks to me very much like it should be a class (it is very rare to write a struct in .NET, and usually to denote "values" - a customer isn't a "value"). And public fields are also very much discouraged.
Note that currently you are (because it is a struct) actually copying the Cust_Info whenever you fetch it from (or place it in) the list; that isn't necessarily what you intend...
You can try something like
ArrayList arr = new ArrayList();
for (int iIndex = 0; iIndex < arr.Count; iIndex++)
{
object o = arr[iIndex];
}
But I would rather go with
List Class and List.Count Property
for(int i=0; i<Customer_Details.Count/*or.Length*/; i++)
Customer_Details[i] = something;

How do I create a string from one row of a two dimensional rectangular character array in C#?

I have a 2 dimensional array, like so:
char[,] str = new char[2,50];
Now, after I've stored contents in both str[0] and str[1], how do I store it in a
string[] s = new string[2];
?
I tried
s[0] = str[0].ToString();
but that seems to be an error: VC# expects 'two' indices within the braces, which means I can convert only a character from the array. Is there a way to convert the entire str[0] to a string? Or is changing it to a jagged array the only solution?
A jagged array is almost always the best solution for a variety of reasons, and this is one good example. There is so much more flexibility available with an array of arrays than with a multi-dimensional array. In this case, once you have the values in an array of chars, then a constructor on the string class can be used to create a string from it.
Also, the jagged array would be composed of "vectors" (i.e., a single-dimensional arrays with a zero-lower-bound index), which are much more preferment in .Net because they are given special treatment by the CLR.
So without knowing what the rest of your program is doing, that would be my recommendation.
If you do attempt to construct a string manually by looping through the array indexes, instead of using a jagged array, then I recommend using the StringBuilder class to do it.
I just banged this out, but it should be something like this:
// For the multi-dimentional array
StringBuilder sb = new StringBuilder();
for (int stringIndex = 0; stringIndex < s.Length; stringIndex++)
{
sb.Clear();
for (int charIndex = 0; charIndex < str.UpperBound(1); charIndex++)
sb.Append(str[stringIndex,charIndex]);
s[stringIndex] = sb.ToString();
}
// For the jagged array
for (int index = 0; index < s.Length; index++)
s[index] = new string(str[index]);
Assuming the dimensions are fixed as 2x50:
char[,] str = new char[2,50];
// populate str somehow
// chose which of the strings we want (the 'row' index)
int strIndex = 0;
// create a temporary array (faster and less wasteful than using a StringBuilder)
char[] chars = new chars[50];
for (int i = 0; i < 50; i++)
chars[i] = str[strIndex, i];
string s = new string[chars];
This would be easier and more performant if you used a jagged array:
char[][] str = new char[2][];
Then you could write:
string s = new string(characters[0]);
I would agree with using a jagged array. You can use this helper method to initialize a jagged array:
static T[][] InitJaggedArray<T>(int dimension1, int dimension2)
{
T[][] array = new T[dimension1][];
for (int i = 0; i < dimension1; i += 1)
{
array[i] = new T[dimension2];
}
return array;
}
So
char[,] str = new char[2,50];
would become
char[][] str = ArrayHelper.InitJaggedArray<char>(2, 50);
You would then access elements in it like so
str[0, 10] = 'a';
And to make it a string you would do
string s = new string(str[0]);
You can do it with LINQ:
string[] Convert(char[,] chars)
{
return Enumerable.Range(0, chars.GetLength(1))
.Select(i => Enumerable.Range(0, chars.GetLength(0))
.Select(j => chars[j, i]))
.Select(chars => new string(chars.ToArray());
}

Categories