I have a string of data that I would like to split up, for example my one string contains multiple characters, their stats and abilities they each have.
Full String:
"Andy,135,Punch-Kick-Bite-Headbutt|Tom,120,Bite-Slap-Dodge-Heal|Nathan,105,Bite-Scratch-Tackle-Kick"
So the above string has the characters seperated by "|" and the abilities that are seperated by "-".
I managed to divide them up by each character so its "Andy,135,Punch-Kick-Bite-Headbutt" in one index of array by doing this:
string myString = "Andy,135,Punch-Kick-Bite-Headbutt|Tom,120,Bite-Slap-Dodge-Heal|Nathan,105,Bite-Scratch-Tackle-Kick";
string[] character = myString.ToString().Split('|');
for (int i = 0; i < character.Length; i++)
{
Debug.Log("Character data: " + character[i].ToString());
}
Now How would I turn something like "Andy,135,Punch-Kick-Bite-Headbutt" and only retrieve the stats into a stat array so its "Andy,135" and pull Abilities into a string array so it is: "Punch-Kick-Bite-Headbutt"
So I would have my statArray as "Andy,135" and abilityArray as "Punch-Kick-Bite-Headbutt"
Well I would strongly recommend defining class to store that data:
public class Character
{
public string Name { get; set; }
public int Stat { get; set; }
public string[] Abilities { get; set; }
}
The I would write following LINQ:
// First split by pipe character to get each character (person)
// in raw format separately
var characters = longString.Split('|')
// Another step is to separate each property of a character,
// so it can be used in next Select method.
// Here we split by comma
.Select(rawCharacter => rawCharacter.Split(','))
// Finally we use splitted raw data and upon this, we create
// concrete object with little help of casting to int and
// assign abilities by splitting abilities list by hyphen -
.Select(rawCharacter => new Character()
{
Name = rawCharacter[0],
Stat = int.Parse(rawCharacter[1]),
Abilities = rawCharacter[2].Split('-'),
})
.ToArray();
Related
I've the following string that I get from a method. I would like to parse it and make pairs. The order of input string will not change.
INPUT:
ku=value1,ku=value2,ku=value3,ku=value4,ku=value5,lu=value6,lu=value7,lu=value8,lu=value9
OUTPUT
Name value1
Title value2
School value3
.
.
.
Age value9
I think I can read through the string and assign value to the left hand side as I go and so on. However, I am very new to C#.
Use string.Split and split imput string to list key-value pair then split each pair to key and value. Tahts all.
You can do something like this:
void Main()
{
string str = "ku=value1,ku=value2,ku=value3,ku=value4,ku=value5,lu=value6,lu=value7,lu=value8,lu=value9";
var tempStr = str.Split(',');
var result = new List<KeyValue>();
foreach(var val in tempStr)
{
var temp = val.Split('=');
var kv = new KeyValue();
kv.Name = temp[0];
kv.Value = temp[1];
result.Add(kv);
}
}
public class KeyValue
{
public string Name {get;set;}
public string Value{get;set;}
}
If you don't need the first part you can do this using String split as follow
Split String on , using String.Split method creating sequence of string {"ku=value1","ku=value2",...}
Use Linq's Select method to apply an additional transformation
Use Split again on each item on the '=' character
Select the item to the right of the '=', at index 1 of the newly split item
Loop through everything and print your results
Here's the code
var target = "ku=value1,ku=value2,ku=value3,ku=value4,ku=value5,lu=value6,lu=value7,lu=value8,lu=value9";
var split = target.Split(',').Select(a=>a.Split('=')[1]).ToArray();
var names = new[]{"Name","Title","School",...,"Age"};
for(int i=0;i<split.Length;i++)
{
Console.WriteLine(names[i]+"\t"+split[i]);
}
If you want to find out more about how to use these methods you can look at the MSDN documentation for them :
String.Split(char[]) Method
Enumerable.Select Method
I suggest to try this way. Split() plus regular expression
string inputString = "ku=value1,ku=value2,ku=value3,ku=value4,ku=value5,lu=value6,lu=value7,lu=value8,lu=value9";
string pattern = "(.*)=(.*)";
foreach(var pair in inputString.Split(','))
{
var match = Regex.Match(pair,pattern);
Console.WriteLine(string.Format("{0} {1}",match.Groups[1].Value, match.Groups[2].Value));
}
Hi there I have a string return from url like that :
{ "Title": "Star Wars", "Year": "1977", "Rated":"3" }
How can I pick up such title, rating, Year without using Json library?
You can try to do it this way :
var str = #"{ ""Title"": ""Star Wars"", ""Year"": ""1977"", ""Rated"":""3"" }";
//remove "{" and "}" from string
var result = str.Trim('{', '}');
//separate each property-value pairs, and remove leading & trailing white spaces
var pairs = result.Split(',').Select(o => o.Trim()).ToArray();
foreach (var pair in pairs)
{
//separate key from it's value and remove leading & trailing white spaces
var keyValue = pair.Split(':').Select(o => o.Trim()).ToArray();
//print result
Console.WriteLine("{0} = {1}", keyValue[0], keyValue[1]);
}
UPDATE :
I agree with #pickypg comment, manually doing set of string manipulation operations isn't the ultimate way to handle JSON. This is better only on specific case: handling small JSON containing 'safe' string. If you're looking for general & robust approach, no one will argue with suggestion to use proven JSON library like JSON.NET. Also agree about using .Trim() instead of twice Replace(), hence updated my code a bit.
If you need to parse Json you should use a library to do it properly. Well, this solution can be a little overkill but you could do something like this:
Regex regex = new Regex("\"(?<field>.+?)\":\\s*\"(?<value>.*?)\"");
Match match = regex.Match("{ \"Title\": \"Star Wars\", \"Year\": \"1977\", \"Rated\":\"3\" }");
while (match.Success)
{
Console.WriteLine("Field: "+match.Groups["field"].Value+ ", Value: "+match.Groups["value"].Value);
match = match.NextMatch();
}
this is not valid json, you'd have to manually parse like split.
Parse error on line 4:
..."1977", "Rated"}
---------------------^
Expecting ':'
Try this
string[] words = s.Split(' ');
foreach (string word in words)
{
Console.WriteLine(word);
}
Class code added ignore above:
public class RootObject
{
public string Title { get; set; }
public string Year { get; set; }
public string Rated { get; set; }
}
using json2csharp
I'm working in C# and I have lots of strings containing addresses, such as:
10 Downing Street
Birch Lane 7
Palm Creek 8 Street
84 Chancellor Place
Battle on the Somme 56
and so on.
I need to split these strings into a numeric part(such as "10" or "7")and a textual part (such as "Downing street" or "Birch Lane").
Oh, and I was asked not to use RegEx.
I've tried already to split them in the spaces like this:
string s ="84 Chancellor place";
string [] words = s.Split(' ');
Problem is that (of course) it doesn't split all string the same way, so I can't always exclude the number from the rest of the text (I don't always know that the number is in words[0] for example, and the textual parts is in different cells and not fused together).
I would much appreciate your help to find a way to extract the digits.
Edit:
Desired outputs in each example:
string1=10 string2=Downing Street
string1=7 string2=Birch Lane
string1=8 string2=Palm Creek Street
string1=84 string2=Chancellor Place
string1=56 string2=Battle on the Somme
You could use this loop to initialize a List<Address> with the help of string.Split and int.TryParse:
List<Address> addresses = new List<Address>();
foreach (string str in strings)
{
Address addr = new Address();
addresses.Add(addr);
int num, numIndex = int.MinValue;
string[] tokens = str.Split(new[]{' '}, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < tokens.Length; i++)
{
if (int.TryParse(tokens[i], out num))
{
addr.Number = num;
numIndex = i;
break;
}
}
if (addr.Number.HasValue)
{
// join the rest with white-spaces to the street name skipping the number
addr.Street = string.Join(" ", tokens.Where((s, i) => i != numIndex));
}
else
{
addr.Street = str;
}
}
Used this small class:
class Address
{
public int Number { get; set; }
public string Street { get; set; }
}
DEMO
Disclaimer: note that this is not fail-safe at all if the input is arbitrary. There are many streets that contain numbers as well in the world and there are also numbers with chars like "17a".
Basically,
I have text I want to spit out from a block of text. I have the regular expression down for the most part however, It's either too little[skips a section] or too much[reads part of the next section].It basically needs to read text that I extracted from a bank statement.I already tried reading up on regular expressions more, however I still have no clue as to what to do.
Heres a bit of a sample for you guys to understand what I'm trying to do.
_4XXXXXXXXXXXXXX9_
_SOU THE HOME DEPOT 431 POMPANO BEACH * FL
AUT 020112 DDA PURCHASE_
_2/1_DEBIT POS_3.15_
The underscores are basically parts I want to extract. Basically everything except the DEBIT POS basically.
And the regex I'm using is:
\A
(?<SerialNumber>\b[0-9]{13,16}\b)
(?<Description>.) 'PROBLEM HERE'
(?<PostingDate>
(?:1[0-2]|[1-9])/(?:3[01]|[12][0-9]|[1-9]))
(?<Amount>[,0-9]+\.[0-9]{2})
\Z
I cant set the Description to be from any length of characters because I don't know the maximum length that the text portion will be. I also don't know if it's 2 lines for description or just 1. Thats mainly whats confusing me.
I imagine you want to join every four lines together as one line first:
var file = #"C:\temp.txt";
var lines = System.IO.File.ReadAllLines(file);
var buffer = new List<String>();
for (var i = 0; i < lines.Length; i++ )
{
if (i % 4 == 0) { buffer.Add(""); }
buffer[buffer.Count - 1] += lines[i] + " ";
}
buffer.ForEach(b => Console.WriteLine(b));
Then you can actually parse each entry in buffer as if it's one line. This can be done easily using either regex or just string Substrings. Far easier than trying to do it across lines.
The above code isn't the cleanest, but it works.
Look like another simple answer of don't use Regex. If each of these are lines, it wouldn't be that hard to File.ReadAllLines() and parse each line.
public class Order
{
public string SerialNumber { get; set; }
public string Description { get; set; }
public DateTime PostingDate { get; set; }
public Decimal Amount { get; set; }
public void SetSerialNumberFromRaw(string serialNumber)
{
// Convert to required type, etc.
this.SerialNumber = <someConvertedValue>;
}
public void <OtherNeededValueConverters>
}
List<string> lines = File.ReadAlllines("<filename").ToList();
List<Order> orders = new List<Order>();
Order currentOrder = null;
foreach (string line in lines)
{
if (currentOrder = null)
{
currentOrder = new Order();
orders.Add(currentOrder);
currentOrder.SetSerialNumberFromRaw(line);
}
else
{
if (line.Contains("DEBIT POS", CultureInfo.CurrentCultureIngoreCase))
{
currentOrder.SetPostingDateAndAmount(line);
currentOrder = null;
}
else
{
currentOrder.SetAppendDescription(line);
}
}
}
So at the moment our ERP/PSA software produces an EFT (Electronic Fund Transfer) .txt file which contains Bank and employee bank information which is then sent to the bank.
Problem is as follows the format to which the EFT File is currently being produced is US standard and not suitable to Canadian bank standards. But I have the required canadian bank standard format.
The format of the file is all about number of columns in a file and the number of characters they contain (if the data for the column doesnt reach the number of characters it is filled with spaces).
So I.e.
1011234567Joe,Bloggs 1234567
And for example lets say I try transform to Canadian Standard
A101Joe,Bloggs 1234567 1234567
Where for example "A" needs to be added to first line in the record.
I'm just wondering how to go about a task like this in C#
I.e.
Read in text file.
Line by Line parse data in terms of start and end of characters
Assign values to variables
Rebuild new file with these variables with different ordering and additional data
I don't have my IDE open so my syntax might be a tad off, but I'll try to point you in the right direction. Anyways, what fun would it be to give you the solution outright?
First you're going to want to get a list of lines:
IEnumerable<string> lines = text.Split('\n');
You said that the columns don't have delimiters but rather are of fixed widths, but you didn't mention where the columns sizes are defined. Generally, you're going to want to pull out the text of each column with
colText = line.Substring(startOfColumn, lengthOfColumn);
For each column you'll have to calculate startOfColumn and lengthOfColumn, depending on the positions and lengths of the columns.
Hopefully that's a good enough foundation for you to get started.
I think that your best bet is to create a class to hold the logical data that is present in the file and have methods in this class for parsing the data from a given format and saving it back to a given format.
For example, assume the following class:
public class EFTData
{
public string Name { get; set; }
public string RoutingNumber { get; set; }
public string AccountNumber { get; set; }
public string Id { get; set; }
public void FromUSFormat(string sLine)
{
this.Id = sLine.Substring(0, 3);
this.RoutingNumber = sLine.Substring(3, 7);
this.Name = sLine.Substring(10, 20);
this.AccountNumber = sLine.Substring(30, 7);
}
public string ToCanadianFormat()
{
var sbText = new System.Text.StringBuilder(100);
// Note that you can pad or trim fields as needed here
sbText.Append("A");
sbText.Append(this.Id);
sbText.Append(this.RoutingNumber);
sbText.Append(this.AccountNumber);
return sbText.ToString();
}
}
You can then read from a US file and write to a Canadian file as follows:
// Assume there is only a single line in the file
string sLineToProcess = System.IO.File.ReadAllText("usin.txt");
var oData = new EFTData();
// Parse the us data
oData.FromUSFormat(sLineToProcess);
// Write the canadian data
using (var oWriter = new StreamWriter("canout.txt"))
{
oWriter.Write(oData.ToCanadianFormat());
}
var lines = File.ReadAllLines(inputPath);
var results = new List<string>();
foreach (var line in lines)
{
results.Add(string.Format("A{0}", line));
}
File.WriteAllLines(outputPath, results.ToArray());