How to parse this information from a string? - string

country residents area capital
Andorra 71201 468 Andorra la Vella
Italien 58133509 301230 Rom
San Marino 29251 61 San Marino
I need to store the information (capital, residents, area, capital) in different variables. How would I go about parsing this? Notice that sometimes there are spaces in the names.
I have tried reading each token ( scanner.next() ) this fails when there are spaces in the capital or country name.
I have tried reading each line and then parsing it but I can't figure out a way to parse everything correctly since there are sometime spaces in the names. (I used indexOf() and substring() )
This is part of a bigger file but there are no spaces in the residents or area field in the entire field.
My try:
while(scanner.hasNext()){
String info = scanner.nextLine();
//parse string
int nameindex = info.indexOf(" ");
System.out.println(info.substring(0,nameindex));
int resindex = info.indexOf(" ", nameindex);
}

I hope you have a multiline string as per your question title. So why don't you simply use a regex for the whole content. Given the string is stored in the variable data
data.split("[ ]{2,}")
This would give the array of data as a whole. So when you have to parse it you can simply do a loop 4 elements at a time
(edit)
or else you can simply use this function... hope this will be easier for you.
List<Map<String, String>> parse(String data){
List<Map<String, String>> dataList = new ArrayList<Map<String, String>>();
String[] lines = data.split("\n");
String[] keys = lines[0].split("[ ]{2,}");
for (int i = 1; i < lines.length; i++) {
String row[] = lines[i].split("[ ]{2,}");
Map<String, String> rowMap = new HashMap<String, String>();
for (int j = 0; j < row.length; j++) {
rowMap.put(keys[j], row[j]);
}
dataList.add(rowMap);
}
return dataList;
}

Related

String Containing only Vowels

Suppose I have a vector of string and it contains strings (aei,ou,a). I want to concatenate them in O(n). After concatination it will become (aeiou,aeia,oua). I want to do concatination in one for loop. How to do it?
Mind you, I haven't checked this, i just made this on the fly. but this sounds like its what you want.
public void variableStrings(arr[] strings) {
List<string> newList = new List<string>();
for(int i = 0; i+1 < strings.Length -1; i++)
{
newList.add(string.Format("{0}{1}",strings[i],strings[i+1]));
}
}

c# beginner using stream reader to read in a txt file

i'm having trouble reading in a text file which contains 9 sets of three integer values separated by commas. This is what i have done so far, but how would i be able to read through the data going down row one to get a max value?
very stuck with a program the data text file looks like
21,7,11
20,10,12
17,7,18
these represent temperature, height and carbon%
i have read in the file as so
{
string s;
System.IO.StreamReader inputFile = new System.IO.StreamReader(DataFile);
s = inputFile.ReadLine();
int noDataLines = int.Parse(s);
double[,] data = new double[noDataLines, 3];
string[] ss;
is this right if the data is stored in the debug folder as a .txt file?
from here how would i go about getting a max temp(ie only reading the first vertical column of data)?
We can simply use mixture of System.IO File.ReadLines() method and LINQ .ToList() in order to read all text lines to List<string>. At this point we can just iterate through the collection parsing double values from text lines :
List<string> lines = File.ReadLines("filepath").ToList();
List<int[]> values = new List<int[]>();
int[] temp = new int[3];
for (int i = 0; i < lines.Count; i++)
{
string[] strValues = lines[i].Split(',');
for (int i2 = 0; i2 < strValues.Length; i2++)
temp[i2] = Convert.ToInt32(strValues[i2]);
values.Add(temp.ToArray());
}
Or we can use LINQ :
List<string> lines = File.ReadLines("filepath").ToList();
List<int[]> values = new List<int[]>();
int[] temp = new int[3];
for (int i = 0; i < lines.Count; i++)
values.Add(lines[i].Split(',')
.Select(l => Convert.ToInt32(l)).ToArray());

Count the number of frequency for different characters in a string

i am currently tried to create a small program were the user enter a string in a text area, clicks on a button and the program counts the frequency of different characters in the string and shows the result on another text area.
E.g. Step 1:- User enter:- aaabbbbbbcccdd
Step 2:- User click the button
Step 3:- a 3
b 6
c 3
d 1
This is what I've done so far....
public partial class Form1 : Form
{
Dictionary<string, int> dic = new Dictionary<string, int>();
string s = "";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
s = textBox1.Text;
int count = 0;
for (int i = 0; i < s.Length; i++ )
{
textBox2.Text = Convert.ToString(s[i]);
if (dic.Equals(s[i]))
{
count++;
}
else
{
dic.Add(Convert.ToString(s[i]), count++);
}
}
}
}
}
Any ideas or help how can I countinue because till now the program is giving a run time error when there are same charachter!!
Thank You
var lettersAndCounts = s.GroupBy(c=>c).Select(group => new {
Letter= group.Key,
Count = group.Count()
});
Instead of dic.Equals use dic.ContainsKey. However, i would use this little linq query:
Dictionary<string, int> dict = textBox1.Text
.GroupBy(c => c)
.ToDictionary(g => g.Key.ToString(), g => g.Count());
You are attempting to compare the entire dictionary to a string, that doesn't tell you if there is a key in the dictionary that corresponds to the string. As the dictionary never is equal to the string, your code will always think that it should add a new item even if one already exists, and that is the cause of the runtime error.
Use the ContainsKey method to check if the string exists as a key in the dictionary.
Instead of using a variable count, you would want to increase the numbers in the dictionary, and initialise new items with a count of one:
string key = s[i].ToString();
textBox2.Text = key;
if (dic.ContainsKey(key)) {
dic[key]++;
} else {
dic.Add(key, 1);
}
I'm going to suggest a different and somewhat simpler approach for doing this. Assuming you are using English strings, you can create an array with capacity = 26. Then depending on the character you encounter you would increment the appropriate index in the array. For example, if the character is 'a' increment count at index 0, if the character is 'b' increment the count at index 1, etc...
Your implementation will look something like this:
int count[] = new int [26] {0};
for(int i = 0; i < s.length; i++)
{
count[Char.ToLower(s[i]) - int('a')]++;
}
When this finishes you will have the number of 'a's in count[0] and the number of 'z's in count[25].

How do I assign a String at Array1[x] to an int at Array2[x]?

I'm trying to organize data I am given from a text file, there are for 4 pieces of info on each line (City, country, population, and date). I wanted to have an array for each so I first put it all into one big String array and started to separate them into 4 arrays but I needed to change the Population info to an int array but it says *
"Type mismatch: cannot convert from element type int to String"
//Separate the information by commas
while(sc.hasNextLine()){
String line = sc.nextLine();
input = line.split(",");
//Organize the data into 4 seperate arrays
for(int x=0; x<input.length;x++){
if(x%4==0){
cities[x] = input[x];
}
if(x%4==1){
countries[x] = input[x];
}
if(x%4==2){
population[x] = Integer.parseInt(input[x]);
}
if(x%4==3){
dates[x] = input[x];
}
}
}
And when I print out the arrays they have a bunch of nulls in between each data. I'm planning to create objects that have the 4 pieces of data so that I can then sort them by population, dates etc... I'm pretty new to working with objects so if anyone has a better way of getting the 4 pieces of data into an object cause I haven't figured a way yet :/ My end goal was to have an array of these objects that I can u different sorting methods on them
I would recommend doing something like this:
public class MyData {
private String city;
private String country;
private Integer population;
private String date;
public MyData(String city, String, country, Integer population, String date) {
this.city = city;
this.country = country;
this.population = population;
this.date = date;
}
// Add getters and setters here
}
And then in the file you're posting about:
...
ArrayList<MyData> allData = new ArrayList<MyData>();
while(sc.hasNextLine()) {
String[] values = sc.nextLine().split(",");
allData.add(new MyData(values[0], values[1], Integer.parseInt(values[2]), values[3]));
}
...
You need an object to store the data in so that you keep the relationship between the values in each column.
Also, I'm just assuming you're using Java here. Which language we're talking about is something you should include in your question or as a tag.
The problem is with your x index. If you look carefully at your "for" you will see that it will insert a value at every 3 positions.
try
int index = 0;
while(sc.hasNextLine()){
String line = sc.nextLine();
input = line.split(",");
//Organize the data into 4 seperate arrays
for(int x=0; x<input.length;x++){
if(x%4==0){
cities[index] = input[x];
}
if(x%4==1){
countries[index] = input[x];
}
if(x%4==2){
population[index] = Integer.parseInt(input[x]);
}
if(x%4==3){
dates[index] = input[x];
}
}
++index;
}

Sorting a string using another sorting order string [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I saw this in an interview question ,
Given a sorting order string, you are asked to sort the input string based on the given sorting order string.
for example if the sorting order string is dfbcae
and the Input string is abcdeeabc
the output should be dbbccaaee.
any ideas on how to do this , in an efficient way ?
The Counting Sort option is pretty cool, and fast when the string to be sorted is long compared to the sort order string.
create an array where each index corresponds to a letter in the alphabet, this is the count array
for each letter in the sort target, increment the index in the count array which corresponds to that letter
for each letter in the sort order string
add that letter to the end of the output string a number of times equal to it's count in the count array
Algorithmic complexity is O(n) where n is the length of the string to be sorted. As the Wikipedia article explains we're able to beat the lower bound on standard comparison based sorting because this isn't a comparison based sort.
Here's some pseudocode.
char[26] countArray;
foreach(char c in sortTarget)
{
countArray[c - 'a']++;
}
int head = 0;
foreach(char c in sortOrder)
{
while(countArray[c - 'a'] > 0)
{
sortTarget[head] = c;
head++;
countArray[c - 'a']--;
}
}
Note: this implementation requires that both strings contain only lowercase characters.
Here's a nice easy to understand algorithm that has decent algorithmic complexity.
For each character in the sort order string
scan string to be sorted, starting at first non-ordered character (you can keep track of this character with an index or pointer)
when you find an occurrence of the specified character, swap it with the first non-ordered character
increment the index for the first non-ordered character
This is O(n*m), where n is the length of the string to be sorted and m is the length of the sort order string. We're able to beat the lower bound on comparison based sorting because this algorithm doesn't really use comparisons. Like Counting Sort it relies on the fact that you have a predefined finite external ordering set.
Here's some psuedocode:
int head = 0;
foreach(char c in sortOrder)
{
for(int i = head; i < sortTarget.length; i++)
{
if(sortTarget[i] == c)
{
// swap i with head
char temp = sortTarget[head];
sortTarget[head] = sortTarget[i];
sortTarget[i] = temp;
head++;
}
}
}
In Python, you can just create an index and use that in a comparison expression:
order = 'dfbcae'
input = 'abcdeeabc'
index = dict([ (y,x) for (x,y) in enumerate(order) ])
output = sorted(input, cmp=lambda x,y: index[x] - index[y])
print 'input=',''.join(input)
print 'output=',''.join(output)
gives this output:
input= abcdeeabc
output= dbbccaaee
Use binary search to find all the "split points" between different letters, then use the length of each segment directly. This will be asymptotically faster then naive counting sort, but will be harder to implement:
Use an array of size 26*2 to store the begin and end of each letter;
Inspect the middle element, see if it is different from the element left to it. If so, then this is the begin for the middle element and end for the element before it;
Throw away the segment with identical begin and end (if there are any), recursively apply this algorithm.
Since there are at most 25 "split"s, you won't have to do the search for more than 25 segemnts, and for each segment it is O(logn). Since this is constant * O(logn), the algorithm is O(nlogn).
And of course, just use counting sort will be easier to implement:
Use an array of size 26 to record the number of different letters;
Scan the input string;
Output the string in the given sorting order.
This is O(n), n being the length of the string.
Interview questions are generally about thought process and don't usually care too much about language features, but I couldn't resist posting a VB.Net 4.0 version anyway.
"Efficient" can mean two different things. The first is "what's the fastest way to make a computer execute a task" and the second is "what's the fastest that we can get a task done". They might sound the same but the first can mean micro-optimizations like int vs short, running timers to compare execution times and spending a week tweaking every millisecond out of an algorithm. The second definition is about how much human time would it take to create the code that does the task (hopefully in a reasonable amount of time). If code A runs 20 times faster than code B but code B took 1/20th of the time to write, depending on the granularity of the timer (1ms vs 20ms, 1 week vs 20 weeks), each version could be considered "efficient".
Dim input = "abcdeeabc"
Dim sort = "dfbcae"
Dim SortChars = sort.ToList()
Dim output = New String((From c In input.ToList() Select c Order By SortChars.IndexOf(c)).ToArray())
Trace.WriteLine(output)
Here is my solution to the question
import java.util.*;
import java.io.*;
class SortString
{
public static void main(String arg[])throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
// System.out.println("Enter 1st String :");
// System.out.println("Enter 1st String :");
// String s1=br.readLine();
// System.out.println("Enter 2nd String :");
// String s2=br.readLine();
String s1="tracctor";
String s2="car";
String com="";
String uncom="";
for(int i=0;i<s2.length();i++)
{
if(s1.contains(""+s2.charAt(i)))
{
com=com+s2.charAt(i);
}
}
System.out.println("Com :"+com);
for(int i=0;i<s1.length();i++)
if(!com.contains(""+s1.charAt(i)))
uncom=uncom+s1.charAt(i);
System.out.println("Uncom "+uncom);
System.out.println("Combined "+(com+uncom));
HashMap<String,Integer> h1=new HashMap<String,Integer>();
for(int i=0;i<s1.length();i++)
{
String m=""+s1.charAt(i);
if(h1.containsKey(m))
{
int val=(int)h1.get(m);
val=val+1;
h1.put(m,val);
}
else
{
h1.put(m,new Integer(1));
}
}
StringBuilder x=new StringBuilder();
for(int i=0;i<com.length();i++)
{
if(h1.containsKey(""+com.charAt(i)))
{
int count=(int)h1.get(""+com.charAt(i));
while(count!=0)
{x.append(""+com.charAt(i));count--;}
}
}
x.append(uncom);
System.out.println("Sort "+x);
}
}
Here is my version which is O(n) in time. Instead of unordered_map, I could have just used a char array of constant size. i.,e. char char_count[256] (and done ++char_count[ch - 'a'] ) assuming the input strings has all ASCII small characters.
string SortOrder(const string& input, const string& sort_order) {
unordered_map<char, int> char_count;
for (auto ch : input) {
++char_count[ch];
}
string res = "";
for (auto ch : sort_order) {
unordered_map<char, int>::iterator it = char_count.find(ch);
if (it != char_count.end()) {
string s(it->second, it->first);
res += s;
}
}
return res;
}
private static String sort(String target, String reference) {
final Map<Character, Integer> referencesMap = new HashMap<Character, Integer>();
for (int i = 0; i < reference.length(); i++) {
char key = reference.charAt(i);
if (!referencesMap.containsKey(key)) {
referencesMap.put(key, i);
}
}
List<Character> chars = new ArrayList<Character>(target.length());
for (int i = 0; i < target.length(); i++) {
chars.add(target.charAt(i));
}
Collections.sort(chars, new Comparator<Character>() {
#Override
public int compare(Character o1, Character o2) {
return referencesMap.get(o1).compareTo(referencesMap.get(o2));
}
});
StringBuilder sb = new StringBuilder();
for (Character c : chars) {
sb.append(c);
}
return sb.toString();
}
In C# I would just use the IComparer Interface and leave it to Array.Sort
void Main()
{
// we defin the IComparer class to define Sort Order
var sortOrder = new SortOrder("dfbcae");
var testOrder = "abcdeeabc".ToCharArray();
// sort the array using Array.Sort
Array.Sort(testOrder, sortOrder);
Console.WriteLine(testOrder.ToString());
}
public class SortOrder : IComparer
{
string sortOrder;
public SortOrder(string sortOrder)
{
this.sortOrder = sortOrder;
}
public int Compare(object obj1, object obj2)
{
var obj1Index = sortOrder.IndexOf((char)obj1);
var obj2Index = sortOrder.IndexOf((char)obj2);
if(obj1Index == -1 || obj2Index == -1)
{
throw new Exception("character not found");
}
if(obj1Index > obj2Index)
{
return 1;
}
else if (obj1Index == obj2Index)
{
return 0;
}
else
{
return -1;
}
}
}

Resources