And is there an elegant linqy way to do it?
What I want to do is create string of given length with made of up multiples of another string up to that length
So for length - 9 and input string "xxx" I get "xxxxxxxxx" (ie length 9)
for a non integral multiple then I'd like to truncate the line.
I can do this using loops and a StringBuilder easily but I'm looking to see if the language can express this idea easily.
(FYI I'm making easter maths homework for my son)
No, nothing simple and elegant - you have to basically code this yourself.
You can construct a string with a number of repeated characters, but ot repeated strings,
i.e.
string s = new string("#", 6); // s = "######"
To do this with strings, you would need a loop to concatenate them, and the easest would then be to use substring to truncate to the desired final length - along the lines of:
string FillString(string text, int count)
{
StringBuilder s = new StringBuilder();
for(int i = 0; i <= count / text.Length; i++)
s.Add(text);
return(s.ToString().Substring(count));
}
A possible solution using Enumerable.Repeat.
const int TargetLength = 10;
string pattern = "xxx";
int repeatCount = TargetLength / pattern.Length + 1;
string result = String.Concat(Enumerable.Repeat(pattern, repeatCount).ToArray());
result = result.Substring(0, TargetLength);
Console.WriteLine(result);
Console.WriteLine(result.Length);
My Linqy (;)) solution would be to create an extension method. Linq is language integrated query, so why the abuse? Im pretty sure it's possible with the select statement of linq since you can create new (anonymous) objects, but why...?
Related
I have searched allot on google without any results I am looking for
I would like to get a numeric value from any string in C#
Ex.
var myString = "Oompa Loompa";
var numericoutput = convertStringToNumericValue(myString);
output/value of numericoutput is something like 612734818
so when I put in another string let say "C4rd1ff InTernaT!onal is # gr3at place#"
the int output will be something like 73572753.
The Values must stay constant, for example so if I enter the same text again of "Oompa Loompa" then I get 612734818 again.
I thought maybe in the way of using Font Family to get the char index of each character, but I don't know where to start with this.
The reason for this is so that I can use this number to generate an index out of a string with other data in it, and with the same input string, get that same index again to recall the final output string for validation.
Any help or point in the right direction would be greatly appreciated
Thanks to Tim I ended up doing the following:
var InputString = "My Test String ~!##$%^&*()_+{}:<>?|";
byte[] asciiBytes = Encoding.ASCII.GetBytes(InputString);
int Multiplier = 1;
int sum = 0;
foreach (byte b in asciiBytes)
{
sum += ((int)b) * Multiplier;
Multiplier++;
}
Obviously this will not work for 1000's of characters, but it is good enough for short words or sentences
int.MaxValue = 2 147 483 647
As an alternative to converting the string to it's bytes, and if a hash won't meet the requirements, here are a couple of shorter ways to accomplish getting a numeric value for a string:
string inputString = "My Test String ~!##$%^&*()_+{}:<>?|"
int multiplier = 0;
int sum = 0;
foreach (char c in inputString)
{
sum += ((int)c) * ++multiplier;
}
The above code outputs 46026, as expected. The only difference is it loops through the characters in the string and gets their ASCII value, and uses the prefix ++ operator (Note that multiplier is set to 0 in this case - which is also the default for int).
Taking a cue from Damith's comment above, you could do the same with LINQ. Simply replace the foreach above with:
sum = inputString.Sum(c => c * ++multiplier);
Finally, if you think you'll need a number larger than Int32.MaxValue, you can use an Int64 (long), like this:
string inputString = "My Test String ~!##$%^&*()_+{}:<>?|"
int multiplier = 0;
long largeSum = 0;
foreach (char c in inputString)
{
largeSum += ((int)c) * ++multiplier;
}
Is there a way to store every 2 characters in a string?
e.g.
1+2-3-2-3+
So it would be "1+", "2-", "3-", "2-", "3+" as separate strings or in an array.
The simplest way would be to walk your string with a loop, and take two-character substrings from the current position:
var res = new List<string>();
for (int i = 0 ; i < str.Length ; i += 2)
res.Add(str.Substring(i, 2));
An advanced solution would do the same thing with LINQ, and avoid an explicit loop:
var res = Enumerable
.Range(0, str.Length/2)
.Select(i => str.Substring(2*i, 2))
.ToList();
The second solution is somewhat more compact, but it is harder to understand, at least to someone not closely familiar with LINQ.
This is a good problem for a regular expressio. You could try:
\d[+-]
Just find how to compile that regular expression (HINT) and call a method that returns all occurrences.
Use a for loop, and extract the characters using the string.Substring() method, ensuring you do not go over the length of the string.
e.g.
string x = "1+2-3-2-3+";
const int LENGTH_OF_SPLIT = 2;
for(int i = 0; i < x.Length(); i += LENGTH_OF_SPLIT)
{
string temp = null; // temporary storage, that will contain the characters
// if index (i) + the length of the split is less than the
// length of the string, then we will go out of bounds (i.e.
// there is more characters to extract)
if((LENGTH_OF_SPLIT + i) < x.Length())
{
temp = x.Substring(i, LENGTH_OF_SPLIT);
}
// otherwise, we'll break out of the loop
// or just extract the rest of the string, or do something else
else
{
// you can possibly just make temp equal to the rest of the characters
// i.e.
// temp = x.Substring(i);
break; // break out of the loop, since we're over the length of the string
}
// use temp
// e.g.
// Print it out, or put it in a list
// Console.WriteLine(temp);
}
I know this is going to be an easy answer but I am new to C#. There is a lot of answers on for different types of splits, but I cannot find one for this problem. I am trying to split a string into two by alternating characters.
The example would be: string example = "stackoverflow" and the output would be "sakvrlo" and "tcoefo".
If it is an odd number of characters it does not matter if the two new strings are of different lengths.
Thanks!
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
string source = "some string to split";
// ALTERNATE: if you want an explicitly typed char[]
// char[] source = "some string to split".ToCharArray();
for( int i = 0; i < source.Length; i++ )
{
if( i % 2 == 0 )
{
sb1.Append( source[i] );
}
else
{
sb2.Append( source[i] );
}
}
Notes:
There is no BCL method that I am aware of that does this automatically (e.g. string.SplitAlternating().
Since the size of the string is known, the StringBuilders can be initialized with a fixed buffer size.
LINQ solution (#usr's answer) is cleaner but slower (if it matters, which is probably rarely).
If performance truly does matter, the fastest way is probably to obtain a pointer to the start of the original char array and iterate by incrementing two separate pointers created by two char arrays declared using stacalloc. Subsequently, those two char arrays can then be passed as an argument to string's constructor. Make sure to append null terminators.
var a = new string(source.Where((c,i) => i % 2 == 0).ToArray());
var b = new string(source.Where((c,i) => i % 2 != 0).ToArray());
I got a little problem here, i'm looking for a better way to split Strings.
For example i receive a String looking like this.
0000JHASDF+4429901234ALEXANDER
I know the pattern the string is built with and i have an array of numbers like this.
4,5,4,7,9
0000 - JHASDF - +442 - 9901234 - ALEXANDER
It is easy to split the whole thing up with the String MID command but it seems to be slow when i receive a file containing 8000 - 10000 datasets.
So any suggestion how i can make this faster to get the data in a List or an Array of Strings?
If anyone knows how to do this for example with RegEx.
var lengths = new[] { 4, 6, 4, 7, 9 };
var parts = new string[lengths.Length];
// if you're not using .NET4 or above then use ReadAllLines rather than ReadLines
foreach (string line in File.ReadLines("YourFile.txt"))
{
int startPos = 0;
for (int i = 0; i < lengths.Length; i++)
{
parts[i] = line.Substring(startPos, lengths[i]);
startPos += lengths[i];
}
// do something with "parts" before moving on to the next line
}
Isn't mid a VB method?
string firstPart = string.Substring(0, 4);
string secondPart = string.Substring(4, 5);
string thirdPart = string.Substring(9, 4);
//...
Perhaps something like this:
string[] SplitString(string s,int[] parts)
{
string[] result=new string[parts.Length];
int start=0;
for(int i=0;i<parts.Length;i++)
{
int len=parts[i];
result[i]=s.SubString(start, len);
start += len;
}
if(start!=s.Length)
throw new ArgumentException("String length doesn't match sum of part lengths");
return result;
}
(I didn't compile it, so it probably contains some minor errors)
As the Mid() function is VB, you could simply try
string.Substring(0, 4);
and so on.
The Regex Split Method would be a possibility, but since you don't have a specific delimiter in the string then I doubt it will be of any use and unlikely to be any faster.
String.Substring is also a possibility. You use it like: var myFirstString = fullString.Substring(0, 4)
I know this is late, but in the Microsoft.VisualBasic.FileIO namespace, you can find the textfieldparser and it would do a better job handling your issue. Here is a link to MSDN - https://msdn.microsoft.com/en-us/library/zezabash.aspx with an explanation. The code is in VB, but you can easily convert it to C#. You will need to add a reference to the Microsoft.VisualBasic.FileIO namespace as well. Hope this helps anyone stumbling on this question in the future.
Here is what it would look like in vb for the questioner's issue:
Using Reader As New Microsoft.VisualBasic.FileIO.
TextFieldParser("C:\TestFolder\test.log")
Reader.TextFieldType =
Microsoft.VisualBasic.FileIO.FieldType.FixedWidth
Reader.SetFieldWidths(4, 6, 4, 7, 9)
Dim currentRow As String()
While Not Reader.EndOfData
Try
currentRow = Reader.ReadFields()
Dim currentField As String
For Each currentField In currentRow
MsgBox(currentField)
Next
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message &
"is not valid and will be skipped.")
End Try
End While
End Using
I'm using the .Net micro framework so the StringBuilder is not available.
I have seen some code from apt professionals to use an Arraylist of chars to concat and build strings, as opposed to the + operator. They essentially build a managed code StringBuilder.
Is there a performance advantage to this? Assume the number of concatenations are higher than 10 and string lengths are also larger than 10.
No, don't use an ArrayList of char values. That will box every char - performance will be horrible, as will memory usage. (Size of a reference + size of a boxed char for each character... yikes!)
Use a char[] internally and "resize" it (create a new array and copy the contents in) when you need to, perhaps doubling in size each time. (EDIT: You don't resize it to the exact size you need - you would start off with, say, 16 chars and keep doubling - so most Append operations don't need to "resize" the array.)
That's similar to how StringBuilder works anyway. (It's even closer to how Java's StringBuilder works.)
I suggest you actually build your own StringBuilder type with the most important members. Unit test the heck out of it, and profile where appropriate.
Let me know if you want a short example.
The only reason that using an ArrayList of chars to build a string would be considered performant is if you compare it to something that has really bad performance. Concatenating a huge string using += would be an example of something that would have such bad performance.
You can make the string concatenation a lot more efficient if you just concatenate into several shorter strings instead of one large string.
This code, for example:
string[] parts = new string[1000];
for (int i = 0; i < parts.Length; i++) {
string part = String.Empty;
for (int j=0; j < 100; j++) {
part += "*";
}
parts[i] = part;
}
string result = String.Concat(parts);
Is about 450 times faster than this code:
string result = string.Empty;
for (int i = 0; i < 100000; i++) {
result += "*";
}
A StringBuilder is still faster, but it's only about four times faster than the first example. So by using shorter strings you can cut the time by 99.78%, and using a StringBuilder would only cut another 0.16%.