How to swap huge string - c#

I have huge string e.g (This is just the part, the string looks same it has just a bit different values).
string numbers = "48.7465504247904 9.16364437205161 48.7465666577545 9.16367275419435 48.746927738083 9.16430761814855 48.7471066512883 9.16462219521963 48.7471147950429";
So I have to swap the whole number e.g.
Output should be:
9.16364437205161 48.7465504247904
Also I need to swap the first and second part.
So I've tried to split the string, and then to replace the old one with the new one.
string numbers = "48.7465504247904 9.16364437205161 48.7465666577545 9.16367275419435 48.746927738083 9.16430761814855 48.7471066512883 9.16462219521963 48.7471147950429";
string output = "";
double first = 0;
double second = 0;
for (int i = 0; i < numbers.Length; i++)
{
numbers.Split(' ');
first = numbers[0];
second = numbers[1];
}
output = numbers.Replace(numbers[1], numbers[0]);
Console.WriteLine(output);
But my variable first always after the loop has the value 52.
Right now my output is: 44.7465504247904 9.16364437205161, it changed the first part, also it calculates somehow -4
.

You're not assigning anything to the value coming back from .Split and, if I read this right, you're also iterating each character in the numbers array for unclear reasons.
Using .Split is all you need ... well, and System.Linq
using System.Linq;
// ...
string SwapNumbers(string numbers) {
return numbers.Split(' ').Reverse().Join();
}
The above assumes you want to reverse the whole series of numbers. It absolutely does not swap 1,2 then swap 3,4 etc. If that's what you're looking for, it's a bit more involved and I'll add that in a second for funsies.
string SwapAlternateNumbers(string numbersInput) {
var wholeSeries = numbersInput.Split(' ').ToList();
// odd number of inputs
if (wholeSeries.Count % 2 != 0) {
throw new InvalidOperationException("I'm not handling this use case for you.");
}
var result = new StringBuilder();
for(var i = 0; i < wholeSeries.Count - 1; i += 2) {
// append the _second_ number
result.Append(wholeSeries[i+1]).Append(" ");
// append the _first_ number
result.Append(wholeSeries[i]).Append(" ");
}
// assuming you want the whole thing as a string
return result.ToString();
}
Edit: converted back to input and output string. Sorry about the enumerables; that's a difficult habit to break.

here
public static void Main()
{
string nums = "48.7465504247904 9.16364437205161 48.7465504247904 9.16364437205161";
var numbers = nums.Split(' ');
var swapped = numbers.Reverse();
Console.WriteLine("Hello World {"+string.Join(" ",swapped.ToArray())+"}");
}

Related

Find index locations of a specified letter in a string

My apologies if I didn't explain it clear the first time. I have edited my explanation further in bold below.
In the program below user enters a word and then enters a letter which the user would like to replace with any character. For instance, user enter's a word "Hello" and the replacement letter is "l" with "$". So "Hello" will become "He$$o". First, the goal is to find the location of "l" (example - 2,3) and then replace the element in that specific location.
I started by finding the location of "l" and storing it in a findIndex array. Every time I run the program I get "22222" stored in findIndex[] array. At this point, I am not even sure if I am even applying the right logic. Any advice will be appreciated! Please don't use LINQ.
public static void RemoveSpecifiedCharacters()
{
Console.WriteLine("\nWrite a word/sentence: ");
string myString = Console.ReadLine();
Console.Write("Type the character you would like to replace: ");
string myCharacter = Console.ReadLine();
int[] findIndex = new int[myString.Length];
for (int i = 0; i < myString.Length; i++)
{
findIndex[i] = myString.IndexOf(myCharacter, 0);
}
for (int i = 0; i < findIndex.Length; i++)
{
Console.Write(findIndex[i]);
}
}
This is probably what you want :
public static void RemoveSpecifiedCharacters()
{
Console.WriteLine("\nWrite a word/sentence: ");
string myString = Console.ReadLine();
Console.Write("Type the character you would like to replace: ");
string myCharacter = Console.ReadLine();
List<int> findIndex = new List<int>();
int offs = 0;
while (offs < myString.Length)
{
offs = myString.IndexOf(myCharacter, offs);;
if (offs == -1)
break;
findIndex.Add(offs);
offs++;
}
for (int i = 0; i < findIndex.Count; i++)
{
Console.Write(findIndex[i]);
}
}
Set an initial offset to the start of the string, try to find index of required character if not found exit, otherwise store the location & increment the offset so the next loop starts after the found position. Then keep looping.
As you do not know how many characters will be found, then a list is better than an array to store the results. It can always be converted to an array with .ToArray() afterwards.
Below should serve the purpose :
var str = "Hello";
var replaced = str.Replace('l', '$');
Even though it's easier to use String.Replace, I just want to give you an explanation why you are getting [2,2,2,2,2] array.
Firstly, IndexOf method returns index of character's first occurence, starting from 0.
Secondly, you are using method overload IndexOf(myCharacter, 0) which "says" that character search should be done always from the start of the string.
To circumvent the issue, you should use IndexOf(myCharacter, i, 1) instead to set the search to start from i-th character, not the start of string.
I guess a simple solution would be to split the string into a character array and then do the comparison?
For example something like:
Console.WriteLine("\nWrite a word/sentence: ");
char[] myString = Console.ReadLine().ToCharArray();
Console.Write("Type the character you would like to replace: ");
char myCharacter = Console.ReadLine().ToCharArray()[0];
int[] findIndex = new int[myString.Length];
int indexCount = 0;
for (int i = 0; i < myString.Length; i++)
{
if (myString[i] == myCharacter)
findIndex[indexCount++] = i;
}
for (int i = 0; i < indexCount; i++)
{
Console.Write(findIndex[i]);
}

Find the first character in a string that is a letter

I am trying to figure out how to look through a string, find the first character that is a letter and then delete from that index point and on.
For example,
string test = "5604495Alpha";
I need to go through this string, find "A" and delete from that point on.
There are several ways to do this. Two examples:
string s = "12345Alpha";
s = new string(s.TakeWhile(Char.IsDigit).ToArray());
Or, more correctly, as Baldrick pointed out in his comment, find the first letter:
s = new string(s.TakeWhile(c => !Char.IsLetter(c)).ToArray());
Or, you can write a loop:
int pos = 0;
while (!Char.IsLetter(s[pos]))
{
++pos;
}
s = s.Substring(0, pos);
A little method to do it:
int getIndexOfFirstLetter(string input) {
var index = 0;
foreach (var c in input)
if (char.IsLetter(c))
return index;
else
index++;
return input.Length;
}
Usage:
var test = "5604495Alpha";
var result = test.Substring(0, getIndexOfFirstLetter(test));
// Returns 5604495
You should break this out to make sure there is a match, and to make sure there is a value at index 0... but it does work for this example case for demonstration purposes.
string test = "5604495Alpha";
var test2 = test.Remove(test.IndexOf(
System.Text.RegularExpressions.Regex.Match(test, "[A-Za-z]").Index));
// test2 = "5604495"

Get a range from two integers

string num = db.SelectNums(id);
string[] numArr = num.Split('-').ToArray();
string num contain for an example "48030-48039";
string[] numArr will therefor contain (48030, 48039).
Now I have two elements, a high and low. I now need to get ALL the numbers from 48030 to 48039. The issue is that it has to be string since there will be telephone numbers with leading zeroes now and then.
Thats why I cannot use Enumerable.Range().ToArray() for this.
Any suggestions? The expected result should be 48030, 48031, 48032, ... , 48039
This should work with your leading zero requirement:
string num = db.SelectNums(id);
string[] split = num.Split('-');
long start = long.Parse(split[0]);
long end = long.Parse(split[1]);
bool includeLeadingZero = split[0].StartsWith("0");
List<string> results = new List<string>();
for(int i = start; i <= end; i++)
{
string result = includeLeadingZero ? "0" : "";
result += i.ToString();
results.Add(result);
}
string[] arrayResults = results.ToArray();
A few things to note:
It assumes your input will be 2 valid integers split by a single hyphen
I am giving you a string array result, personally I would prefer to work with a List<int> in the end
If the first number contains a single leading zero, then all results will contain a single leading zero
It uses long to cater for longer numbers, beware that the max number that will parse is 9,223,372,036,854,775,807, you could double this value (not length) by using ulong
Are you saying this?
int[] nums = new int[numArr.Length];
for (int i = 0; i < numArr.Length; i++)
{
nums[i] = Convert.ToInt32(numArr[i]);
}
Array.Sort(nums);
for (int n = nums[0]; n <= nums[nums.Length - 1]; n++)
{
Console.WriteLine(n);
}
here link
I am expecting your string always have valid two integers, so using Parse instead TryParse
string[] strList = "48030-48039".Split('-').ToArray();
var lst = strList.Select(int.Parse).ToList();
var min = lst.OrderBy(l => l).FirstOrDefault();
var max = lst.OrderByDescending(l => l).FirstOrDefault();
var diff = max - min;
//adding 1 here otherwise 48039 will not be there
var rng = Enumerable.Range(min,diff+1);
If you expecting invalid string
var num = 0;
var lst = (from s in strList where int.TryParse(s, out num) select num).ToList();
This is one way to do it:
public static string[] RangeTest()
{
Boolean leadingZero = false;
string num = "048030-48039"; //db.SelectNums(id);
if (num.StartsWith("0"))
leadingZero = true;
int min = int.Parse(num.Split('-').Min());
int count = int.Parse(num.Split('-').Max()) - min;
if (leadingZero)
return Enumerable.Range(min, count).Select(x => "0" + x.ToString()).ToArray();
else
return Enumerable.Range(min, count).Select(x => "" + x.ToString()).ToArray(); ;
}
You can use string.Format to ensure numbers are formatted with leading zeros. That will make the method work with arbitrary number of leading zeros.
private static string CreateRange(string num)
{
var tokens = num.Split('-').Select(s => s.Trim()).ToArray();
// use UInt64 to allow huge numbers
var start = UInt64.Parse(tokens[0]);
var end = UInt64.Parse(tokens[1]);
// if your start number is '000123', this will create
// a format string with 6 zeros ('000000')
var format = new string('0', tokens[0].Length);
// use StringBuilder to make GC happy.
// (if only there was a Enumerable.Range<ulong> overload...)
var sb = new StringBuilder();
for (var i = start; i <= end; i++)
{
// format ensures that your numbers are padded properly
sb.Append(i.ToString(format));
sb.Append(", ");
}
// trim trailing comma after the last element
if (sb.Length >= 2) sb.Length -= 2;
return sb.ToString();
}
Usage example:
// prints 0000012, 0000013, 0000014
Console.WriteLine( CreateRange("0000012-0000014") );
Three significant issues were brought up in comments:
The phone numbers have enough digits to exceed Int32.MaxValue so
converting to int isn't viable.
The phone numbers can have leading zeros (presumeably for some
international calling?)
The possible range of numbers can theoretically exceed the maximum size of an array (which may have memory issues, and I think may not be represented as a string)
As such, you may need to use long instead of int, and I would suggest using deferred execution if needed for very large ranges.
public static IEnumerable<string> EnumeratePhoneNumbers(string fromAndTo)
{
var split = fromAndTo.Split('-');
return EnumeratePhoneNumbers(split[0], split[1]);
}
public static IEnumerable<string> EnumeratePhoneNumbers(string fromString, string toString)
{
long from = long.Parse(fromString);
long to = long.Parse(toString);
int totalNumberLength = fromString.Length;
for (long phoneNumber = from; phoneNumber <= to; phoneNumber++)
{
yield return phoneNumber.ToString().PadLeft(totalNumberLength, '0');
}
}
This assumes that the padded zeros are already included in the lower bound fromString text. It will iterate and yield out numbers as you need them. This can be useful if you're churning out a lot of numbers and don't need to fill up memory with them, or if you just need the first 10 or 100. For example:
var first100Numbers =
EnumeratePhoneNumbers("0018155500-7018155510")
.Take(100)
.ToArray();
Normally that range would produce 7 billion results which cannot be stored in an array, and might run into memory issues (I'm not even sure if it can be stored in a string); by using deferred execution, you only create the 100 needed.
If you do have a small range, you can still join up your results into a string as you desired:
string numberRanges = String.Join(", ", EnumeratePhoneNumbers("0018155500-0018155510"));
And naturally you can put this array creation into your own helper method:
public static string GetPhoneNumbersListing(string fromAndTo)
{
return String.Join(", ", EnumeratePhoneNumbers("0018155500-0018155510"));
}
So your usage would be:
string numberRanges = GetPhoneNumbersListing("0018155500-0018155510");
A complete solution inspired by the answer by #Dan-o:
Inputs:
Start: 48030
End: 48039
Digits: 6
Expected String Output:
048030, 048031, 048032, 048033, 048034, 048035, 048036, 048037, 048038, 048039
Program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class Program
{
public static void Main()
{
int first = 48030;
int last = 48039;
int digits = 6;
Console.WriteLine(CreateRange(first, last, digits));
}
public static string CreateRange(int first, int last, int numDigits)
{
string separator = ", ";
var sb = new StringBuilder();
sb.Append(first.ToString().PadLeft(numDigits, '0'));
foreach (int num in Enumerable.Range(first + 1, last - first))
{
sb.Append(separator + num.ToString().PadLeft(numDigits, '0'));
}
return sb.ToString();
}
}
For Each item In Enumerable.Range(min, count).ToArray()
something = item.PadLeft(5, "0")
Next

Trying to get the largest int in each line of a file and sum the result

When I try and run my code I get the error:
Input string was not in a correct format.
I am trying to find the largest int in each line of a text file and then add them all up.
I am sure that there are no letters in this file and everything is separated by a space.
Here is my code:
int counter = 0;
string line;
List<int> col = new List<int>();
// Read the file and display it line by line.
System.IO.StreamReader file =
new System.IO.StreamReader(label3.Text);
while ((line = file.ReadLine()) != null)
{
int[] storage = new int[10000];
Console.WriteLine(line);
counter++;
string s = line;
string[] words = s.Split(' ');
for (int i = 0; i < words.Length; i++)
{
storage[i] = Convert.ToInt32(words[i]);
}
int large = storage.Max();
col.Add(large);
Console.WriteLine(" ");
foreach (int iii in col)
{
Console.WriteLine(iii);
}
int total = col.Sum();
Console.WriteLine(total);
}
file.Close();
// Suspend the screen.
Console.ReadLine();
It's possible that target string cannot be stored in a 32 bit integer. You can try parsing to ulong type. Take a look at Integral Types Table and Floating-Point Types Table.
Instead of doing Convert.ToInt32(), try int.TryParse(). It will return a bool value telling you if operation succeeded, and it has an out parameter where it will place result of parse operation. TryParse operation is also available on other numeric types if you decide you need them.
E.g.
int val;
string strVal = "1000";
if (int.TryParse(strVal, out val))
{
// do something with val
}
else
{
// report error or skip
}
I did a quick test and it is likely you get the error in the line
storage[i] = Convert.ToInt32(words[i]);
If so, make sure what you are trying to convert is an integer and not an empty string, for example.
I believe that the line in your code that can cause this error is
Convert.ToInt32(words[i]);
Now, when you're running this application in debug mode(which you probably are) in visual studio, you have a way to check what's going on in your program when the exception happens.
At the very very bottom of your screen is going to be some tabs. these tabs include your error list among other things. The ones I like to use are called "Locals" and "Watch". You can use the Locals tab.
When you click on the Locals tab, you should see a tree structure of all the local variables in your program. if you expand the words variable, you should see all the individual members of the array. you should also be able to see the variable i check the i'th member of your words array, and make sure that it's an integer, and not something else.
You're either converting out of size, or attempting to parse a return carriage '/r'
Make sure you're trimming your input.
My solution:
static void Main(string[] args)
{
int linecount = 100;
string path = #"C:\test\test.txt";
Random rand = new Random();
//Create File
StreamWriter writer = new StreamWriter(path, false);
for (int i = 0; i < linecount; i++)
{
for (int j = 0; j < rand.Next(10, 15); j++)
{
writer.Write(rand.Next() + " ");
}
writer.WriteLine("");
}
writer.Close();
//Sum File
long sum = Enumerable.Sum<string>(
(new StreamReader(path)).ReadToEnd().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries),
l => Enumerable.Max(
l.Split(' '),
i => String.IsNullOrEmpty(i.Trim()) ? 0 : long.Parse(i.Trim())
)
);
}

Getting parts of a string and combine them in C#?

I have a string like this: C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg
Now, what I want to do is to dynamically combine the last 4 numbers, in this case its 10000080 as result. My idea was ti split this and combine them in some way, is there an easier way? I cant rely on the array index, because the path can be longer or shorter as well.
Is there a nice way to do that?
Thanks :)
A compact way using string.Join and Regex.Split.
string text = #"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
string newString = string.Join(null, Regex.Split(text, #"[^\d]")); //10000080
Use String.Split
String toSplit = "C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
String[] parts = toSplit.Split(new String[] { #"\" });
String result = String.Empty;
for (int i = 5, i > 1; i--)
{
result += parts[parts.Length - i];
}
// Gives the result 10000080
You can rely on array index if the last part always is the filename.
since the last part is always
array_name[array_name.length - 1]
the 4 parts before that can be found by
array_name[array_name.length - 2]
array_name[array_name.length - 3]
etc
If you always want to combine the last four numbers, split the string (use \ as the separator), start counting from the last part and take 4 numbers, or the 4 almost last parts.
If you want to take all the digits, just scan the string from start to finish and copy just the digits to a new string.
string input = "C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
string[] parts = toSplit.Split(new char[] {'\\'});
IEnumerable<string> reversed = parts.Reverse();
IEnumerable<string> selected = reversed.Skip(1).Take(4).Reverse();
string result = string.Concat(selected);
The idea is to extract the parts, reverse them to keep only the last 4 (excluding the file name) and re reversing to rollback to the initial order, then concat.
Using LINQ:
string path = #"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg";
var parts = Path.GetDirectoryName(path).Split('\\');
string numbersPart = parts.Skip(parts.Count() - 4)
.Aggregate((acc, next) => acc + next);
Result: "10000080"
var r = new Regex(#"[^\d+]");
var match = r
.Split(#"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg")
.Aggregate((i, j) => i + j);
return match.ToString();
to find the number you can use regex:
(([0-9]{2})\\){4}
use concat all inner Group ([0-9]{2}) to get your searched number.
This will always find your searched number in any position in the given string.
Sample Code:
static class TestClass {
static void Main(string[] args) {
string[] tests = { #"C:\Projects\test\whatever\files\media\10\00\00\80\test.jpg",
#"C:\Projects\test\whatever\files\media\10\00\00\80\some\foldertest.jpg",
#"C:\10\00\00\80\test.jpg",
#"C:\10\00\00\80\test.jpg"};
foreach (string test in tests) {
int number = ExtractNumber(test);
Console.WriteLine(number);
}
Console.ReadLine();
}
static int ExtractNumber(string path) {
Match match = Regex.Match(path, #"(([0-9]{2})\\){4}");
if (!match.Success) {
throw new Exception("The string does not contain the defined Number");
}
//get second group that is where the number is
Group #group = match.Groups[2];
//now concat all captures
StringBuilder builder = new StringBuilder();
foreach (var capture in #group.Captures) {
builder.Append(capture);
}
//pares it as string and off we go!
return int.Parse(builder.ToString());
}
}

Categories

Resources