I had a List liRoom which contains a alphanumeric and Alphabetic string For Example
List<string> liRoom = new List<string>() {"Room1","Room2","Room3",
"Room4","Hall","Room5","Assembly",
"Room6","Room7","Room8","Room9};
This List is of type Alphanumeric and Alphabetic so i want to take the max numeric value from this list of string.
I had tried to do it this way
var ss = new Regex("(?<Alpha>[a-zA-Z]+)(?<Numeric>[0-9]+)");
List<int> liNumeric = new List<int>();
foreach (string st in liRoom)
{
var varMatch = ss.Match(st);
liNumeric.Add(Convert.ToInt16(varMatch.Groups["Numeric"].Value));
}
int MaxValue = liNumeric.Max();// Result Must be 9 from above Example.
And
List<int> liNumeric = new List<int>();
foreach (string st in liRoom)
{
liNumeric.Add( int.Parse(new string(st.Where(char.IsDigit).ToArray())));
}
int MaxValue = liNumeric.Max();// Result Must be 9 from above Example.
But both shows error when st is Hall,Assembly
Help me How to do this.
there are few reasons you will get exception in your code. I'm adding few condition for those possible exceptions.
List<int> liNumeric = new List<int>();
foreach (string st in liRoom)
{
// int.Parse will fail if you don't have any digit in the input
if(st.Any(char.IsDigit))
{
liNumeric.Add(int.Parse(new string(st.Where(char.IsDigit).ToArray())));
}
}
if (liNumeric.Any()) //Max will fail if you don't have items in the liNumeric
{
int MaxValue = liNumeric.Max();
}
Please try the following:
List<string> liRoom = new List<string>() {"Room1","Room2","Room3",
"Room4","Hall","Room5","Assembly",
"Room6","Room7","Room8","Room9"};
var re = new Regex(#"\d+");
int max = liRoom.Select(_ => re.Match(_))
.Where(_ => _.Success)
.Max( _ => int.Parse(_.Value));
/*
max = 9
*/
You don't need foreach, it can be done with one statement:
int value = liRoom.Where(x => x.Any(char.IsDigit))
.Select(x => Convert.ToInt32(new String(x.Where(char.IsDigit).ToArray())))
.Max();
It seems odd but it's working. :)
You should add below in your code by checking whether match is success or not
if (varMatch.Success)
{
liNumeric.Add(Convert.ToInt16(varMatch.Groups["Numeric"].Value));
}
Related
I have a text file that contains Values in this Format: Time|ID:
180|1
60 |2
120|3
Now I want to sort them by Time. The Output also should be:
60 |2
120|3
180|1
How can I solve this problem? With this:
var path = #"C:\Users\admin\Desktop\test.txt";
List<string> list = File.ReadAllLines(path).ToList();
list.Sort();
for (var i = 0; i < list.Count; i++)
{
Console.WriteLine(list[i]);
}
I got no success ...
3 steps are necessary to do the job:
1) split by the separator
2) convert to int because in a string comparison a 6 comes after a 1 or 10
3) use OrderBy to sort your collection
Here is a linq solution in one line doing all 3 steps:
list = list.OrderBy(x => Convert.ToInt32(x.Split('|')[0])).ToList();
Explanation
x => lambda expression, x denotes a single element in your list
x.Split('|')[0] splits each string and takes only the first part of it (time)
Convert.ToInt32(.. converts the time into a number so that the ordering will be done in the way you desire
list.OrderBy( sorts your collection
EDIT:
Just to understand why you got the result in the first place here is an example of comparison of numbers in string representation using the CompareTo method:
int res = "6".CompareTo("10");
res will have the value of 1 (meaning that 6 is larger than 10 or 6 follows 10)
According to the documentation->remarks:
The CompareTo method was designed primarily for use in sorting or alphabetizing operations.
You should parse each line of the file content and get values as numbers.
string[] lines = File.ReadAllLines("path");
// ID, time
var dict = new Dictionary<int, int>();
// Processing each line of the file content
foreach (var line in lines)
{
string[] splitted = line.Split('|');
int time = Convert.ToInt32(splitted[0]);
int ID = Convert.ToInt32(splitted[1]);
// Key = ID, Value = Time
dict.Add(ID, time);
}
var orderedListByID = dict.OrderBy(x => x.Key).ToList();
var orderedListByTime = dict.OrderBy(x => x.Value).ToList();
Note that I use your ID reference as Key of dictionary assuming that ID should be unique.
Short code version
// Key = ID Value = Time
var orderedListByID = lines.Select(x => x.Split('|')).ToDictionary(x => Convert.ToInt32(x[1]), x => Convert.ToInt32(x[0])).OrderBy(x => x.Key).ToList();
var orderedListByTime = lines.Select(x => x.Split('|')).ToDictionary(x => Convert.ToInt32(x[1]), x => Convert.ToInt32(x[0])).OrderBy(x => x.Value).ToList();
You need to convert them to numbers first. Sorting by string won't give you meaningful results.
times = list.Select(l => l.Split('|')[0]).Select(Int32.Parse);
ids = list.Select(l => l.Split('|')[1]).Select(Int32.Parse);
pairs = times.Zip(ids, (t, id) => new{Time = t, Id = id})
.OrderBy(x => x.Time)
.ToList();
Thank you all, this is my Solution:
var path = #"C:\Users\admin\Desktop\test.txt";
List<string> list = File.ReadAllLines(path).ToList();
list = list.OrderBy(x => Convert.ToInt32(x.Split('|')[0])).ToList();
for(var i = 0; i < list.Count; i++)
{
Console.WriteLine(list[i]);
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestClass {
public static void main(String[] args) {
List <LineItem> myList = new ArrayList<LineItem>();
myList.add(LineItem.getLineItem(500, 30));
myList.add(LineItem.getLineItem(300, 20));
myList.add(LineItem.getLineItem(900, 100));
System.out.println(myList);
Collections.sort(myList);
System.out.println("list after sort");
System.out.println(myList);
}
}
class LineItem implements Comparable<LineItem>{
int time;
int id ;
#Override
public String toString() {
return ""+ time + "|"+ id + " ";
}
#Override
public int compareTo(LineItem o) {
return this.time-o.time;
}
public static LineItem getLineItem( int time, int id ){
LineItem l = new LineItem();
l.time=time;
l.id=id;
return l;
}
}
I have a list of strings that look like this:
List<string> list = new List<string>;
list.add("AAPL7131221P00590000");
list.add("AAPL7131206C00595000");
list.add("AAPL7131213P00600000");
I would like to remove the date that is between AAPL7 and the next letter which is either C or P, and then add it to a new list. How do I use regex to get: 131221, 131206, or 131212 so I can populate a new list?
You don't need regex for this one, you can just use Substring, assuming that all your inputs will be the same number of characters.
var startingString = "AAPL7"; // holds whatever the starting string is
var input = "AAPL7131221P00590000";
var outputDate = input.Substring(startingString.Length, 6);
So if you wanted to make this a one-liner for making a collection:
List<string> allDates = yourInputValues
.Select(x => x.Substring(startingString.Length, 6))
.ToList();
Consider the following code snippet...
string startPattern = "AAPL7"; // GOOGL, GOOG, etc
List<string> newlist = list
.Select(n => Regex.Match(n, string.Format(#"(?<=^{0})\d+", startPattern)).Value)
.ToList();
//Regex regex = new Regex("(\\w{5})(\\d*)(\\w*)");
Regex regex = new Regex("(\\w*)(\\d{6})([PC])(\\d*)");
List<string> list = new List<string>();
list.Add("AAPL7131221P00590000");
list.Add("AAPL7131206C00595000");
list.Add("AAPL7131213P00600000");
List<string> extracted = new List<string>();
foreach (string item in list)
{
extracted.Add(regex.Split(item)[2]);
}
Is this what you want?
I just add something that may help in case you have the different date length (i.e. 14131 for 31st, January 2014)
string startpart = "AAPL7"; // or whatever
string mainstring = "AAPL714231P00590000"; // or any other input
mainstring = mainstring.Substring(startpart.Length); //this will through away startpart
int index;
if (mainstring.IndexOf("P") >= 0) index = mainstring.IndexOf("P"); //if there is no "P" it gives -1
else index = mainstring.IndexOf("C");
string date = mainstring.Substring(0,index);
i guess it is a safe approach to handle wider cases
I have a class WordCount which has string wordDic and int count. Next, I have a List.
I have ANOTHER List which has lots of words inside it. I am trying to use List to count the occurrences of each word inside List.
Below is where I am stuck.
class WordCount
{
string wordDic;
int count;
}
List<WordCount> usd = new List<WordCount>();
foreach (string word in wordsList)
{
if (usd.wordDic.Contains(new WordCount {wordDic=word, count=0 }))
usd.count[value] = usd.counts[value] + 1;
else
usd.Add(new WordCount() {wordDic=word, count=1});
}
I don't know how to properly implement this in code but I am trying to search my List to see if the word in wordsList already exists and if it does, add 1 to count but if it doesn't then insert it inside usd with count of 1.
Note: *I have to use Lists to do this. I am not allowed to use anything else like hash tables...*
This is the answer before you edited to only use lists...btw, what is driving that requirement?
List<string> words = new List<string> {...};
// For case-insensitive you can instantiate with
// new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
Dictionary<string, int> counts = new Dictionary<string, int>();
foreach (string word in words)
{
if (counts.ContainsKey(word))
{
counts[word] += 1;
}
else
{
counts[word] = 1;
}
}
If you can only use lists, Can you use List<KeyValuePair<string,int>> counts which is the same thing as a dictionary (although I'm not sure it would guarantee uniqueness). The solution would be very similar. If you can only use lists the following will work.
List<string> words = new List<string>{...};
List<string> foundWord = new List<string>();
List<int> countWord = new List<int>();
foreach (string word in words)
{
if (foundWord.Contains(word))
{
countWord[foundWord.IndexOf(word)] += 1;
}
else
{
foundWord.Add(word);
countWord.Add(1);
}
}
Using your WordCount class
List<string> words = new List<string>{...};
List<WordCount> foundWord = new List<WordCount>();
foreach (string word in words)
{
WordCount match = foundWord.SingleOrDefault(w => w.wordDic == word);
if (match!= null)
{
match.count += 1;
}
else
{
foundWord.Add(new WordCount { wordDic = word, count = 1 });
}
}
You can use Linq to do this.
static void Main(string[] args)
{
List<string> wordsList = new List<string>()
{
"Cat",
"Dog",
"Cat",
"Hat"
};
List<WordCount> usd = wordsList.GroupBy(x => x)
.Select(x => new WordCount() { wordDic = x.Key, count = x.Count() })
.ToList();
}
Use linq: Assuming your list of words :
string[] words = { "blueberry", "chimpanzee", "abacus", "banana", "abacus","apple", "cheese" };
You can do:
var count =
from word in words
group word.ToUpper() by word.ToUpper() into g
where g.Count() > 0
select new { g.Key, Count = g.Count() };
(or in your case, select new WordCount()... it'll depend on how you have your constructor set up)...
the result will look like:
First, all of your class member is private, thus, they could not be accessed somewhere out of your class. Let's assume you're using them in WordCount class too.
Second, your count member is an int. Therefore, follow statement will not work:
usd.count[value] = usd.counts[value] + 1;
And I think you've made a mistype between counts and count.
To solve your problem, find the counter responding your word. If it exists, increase count value, otherwise, create the new one.
foreach (string word in wordsList) {
WordCount counter = usd.Find(c => c.wordDic == word);
if (counter != null) // Counter exists
counter.count++;
else
usd.Add(new WordCount() { wordDic=word, count = 1 }); // Create new one
}
You should use a Dictionary as its faster when using the "Contains" method.
Just replace your list with this
Dictionary usd = new Dictionary();
foreach (string word in wordsList)
{
if (usd.ContainsKey(word.ToLower()))
usd.count[word.ToLower()].count++;
else
usd.Add(word.ToLower(), new WordCount() {wordDic=word, count=1});
}
I have a list of strings which includes strings in format: xx#yy
xx = feature name
yy = project name
Basically, I want to split these strings at # and store the xx part in one string array and the yy part in another to do further operations.
string[] featureNames = all xx here
string[] projectNames = all yy here
I am able to split the strings using the split method (string.split('#')) in a foreach or for loop in C# but I can't store two parts separately in two different string arrays (not necessarily array but a list would also work as that can be converted to array later on).
The main problem is to determine two parts of a string after split and then appends them to string array separately.
This is one simple approach:
var xx = new List<string>();
var yy = new List<string>();
foreach(var line in listOfStrings)
{
var split = string.split('#');
xx.Add(split[0]);
yy.Add(split[1]);
}
The above instantiates a list of xx and and a list of yy, loops through the list of strings and for each one splits it. It then adds the results of the split to the previously instantiated lists.
How about the following:
List<String> xx = new List<String>();
List<String> yy = new List<String>();
var strings = yourstring.Split('#');
xx.Add(strings.First());
yy.Add(strings.Last());
var featureNames = new List<string>();
var productNames = new List<string>();
foreach (var productFeature in productFeatures)
{
var parts = productFeature.Split('#');
featureNames.Add(parts[0]);
productNames.Add(parts[1]);
}
How about
List<string> lst = ... // your list containging xx#yy
List<string> _featureNames = new List<string>();
List<string> _projectNames = new List<string>();
lst.ForEach(x =>
{
string[] str = x.Split('#');
_featureNames.Add(str[0]);
_projectNames.Add(str[1]);
}
string[] featureNames = _featureNames.ToArray();
string[] projectNames = _projectNames.ToArray();
You can do something like this:
var splits = input.Select(v => v.Split('#'));
var features = splits.Select(s => s[0]).ToList();
var projects = splits.Select(s => s[1]).ToList();
If you don't mind slightly more code but better performance and less pressure on garbage collector then:
var features = new List<string>();
var projects = new List<string>();
foreach (var split in input.Select(v => v.Split('#')))
{
features.Add(split[0]);
projects.Add(split[1]);
}
But overall I'd suggest to create class and parse your input (more C#-style approach):
public class ProjectFeature
{
public readonly string Project;
public readonly string Feature;
public ProjectFeature(string project, string feature)
{
this.Project = project;
this.Feature = feature;
}
public static IEnumerable<ProjectFeature> ParseList(IEnumerable<string> input)
{
return input.Select(v =>
{
var split = v.Split('#');
return new ProjectFeature(split[1], split[0]);
}
}
}
and use it later (just an example of possible usage):
var projectFeatures = ProjectFeature.ParseList(File.ReadAllLines(#"c:\features.txt")).ToList();
var features = projectFeatures.Select(f => f.Feature).ToList();
var projects = projectFeatures.Select(f => f.Project).ToList();
// ??? etc.
var all_XX = yourArrayOfStrings.Select(str => str.split('\#')[0]); // this will be IENumerable
var all_YY = yourArrayOfStrings.Select(str => str.split('\#')[1]); // the same fot YY. But here make sure that element at [1] exists
The main problem is to determine two parts of a string after split and then appends them to string array separately.
Why the different arrays? Wouldn't a dictionary be more fitting?
List<String> input = File.ReadAllLines().ToList<String>(); // or whatever
var output = new Dictionary<String, String>();
foreach (String line in input)
{
var parts = input.Split('#');
output.Add(parts[0], parts[1]);
}
foreach (var feature in output)
{
Console.WriteLine("{0}: {1}", feature.Key, feature.Value);
}
Try this.
var ls = new List<string>();
ls.Add("123#project");
ls.Add("123#project1");
var f = from c in ls
select new
{
XX = c.Split("#")[0],
YY = c.Split("#")[1]
};
string [] xx = f.Select (x => x.XX).ToArray();
string [] yy = f.Select (x => x.YY).ToArray();
I have an array of strings like so:
[0]Board1
[1]Messages Transmitted75877814
[2]ISR Count682900312
[3]Bus Errors0
[4]Data Errors0
[5]Receive Timeouts0
[6]TX Q Overflows0
[7]No Handler Failures0
[8]Driver Failures0
[9]Spurious ISRs0
just to clarify the numbers in the square brackets indicate the strings position in the array
I want to convert the array of strings to a dictionary with the string to the left of each number acting as the key, for example (ISR Count, 682900312)
I then want to output specific entries in the dictionary to a text box/table in visual studio (which ever is better) it would be preferable for the numbers to be left aligned.
excuse my naivety, I'm a newbie!
Pretty Simple. Tried and Tested
string[] arr = new string[] { "Board1", "ISR Count682900312", ... };
var numAlpha = new Regex("(?<Alpha>[a-zA-Z ]*)(?<Numeric>[0-9]*)");
var res = arr.ToDictionary(x => numAlpha.Match(x).Groups["Alpha"],
x => numAlpha.Match(x).Groups["Numeric"]);
string[] strings =
{
"Board1", "Messages232"
};
Dictionary<string, int> dictionary = new Dictionary<string, int>();
foreach (var s in strings)
{
int index = 0;
for (int i = 0; i < s.Length; i++)
{
if (Char.IsDigit(s[i]))
{
index = i;
break;
}
}
dictionary.Add(s.Substring(0, index), int.Parse(s.Substring(index)));
}
var stringArray = new[]
{
"[0]Board1",
"[1]Messages Transmitted75877814",
"[2]ISR Count682900312",
"[3]Bus Errors0",
"[4]Data Errors0",
"[5]Receive Timeouts0",
"[6]TX Q Overflows0",
"[7]No Handler Failures0",
"[8]Driver Failures0",
"[9]Spurious ISRs0"
};
var resultDict = stringArray.Select(s => s.Substring(3))
.ToDictionary(s =>
{
int i = s.IndexOfAny("0123456789".ToCharArray());
return s.Substring(0, i);
},
s =>
{
int i = s.IndexOfAny("0123456789".ToCharArray());
return int.Parse(s.Substring(i));
});
EDIT: If the numbers in brackets are not included in the strings, remove .Select(s => s.Substring(3)).
Here you go:
string[] strA = new string[10]
{
"Board1",
"Messages Transmitted75877814",
"ISR Count682900312",
"Bus Errors0",
"Data Errors0",
"Receive Timeouts0",
"TX Q Overflows0",
"No Handler Failures0",
"Driver Failures0",
"Spurious ISRs0"
};
Dictionary<string, int> list = new Dictionary<string, int>();
foreach (var item in strA)
{
// this Regex matches any digit one or more times so it picks
// up all of the digits on the end of the string
var match = Regex.Match(item, #"\d+");
// this code will substring out the first part and parse the second as an int
list.Add(item.Substring(0, match.Index), int.Parse(match.Value));
}