I am trying to parse a string of events into a list EventsList, then populate the fields in my listview (title, location, time, and date) with the correct strings from EventList.
The problem I have run into now is that the method used to populate EventsList is returning something that is no where to be found in my string. The string displayed from EventsList is:
System.Collections.GenericList'1[System.String]
If anyone could help me figure out why it is returning that it would be much appreciated - or if there is a better strategy to do this please enlighten me.
List<string> EventsList = new List<string>();
EventsList = EventDetails(EventsList);
List<string> EventDetails(List<string> arEvents)
{
int indexNum = 67;
string events = GetEvents();
//while (indexNum <= 78)
//{
int index1 = (events.IndexOf(indexNum.ToString())) + 2;
int commaIndex = events.IndexOf(",");
if ((commaIndex - index1) <= 0)
{
string Title = events.Substring(index1, 10);
indexNum++;
}
else
indexNum++;
// }
Title = events.Substring(index1, 10);
arEvents.Add(Title);
return arEvents;
}
MainListView.ItemsSource = new List<APBEvent>
{
new APBEvent()
{
EventTitle = GetEvents(),
EventLocation = "line break",
EventTime = EventsList.ToString(),
EventDate = "5/11/18",
},
};
EventsList.ToString()
EventList is list<string> and you can not convert list to string.
If you want to convert list<string> contents to string then you can join the contents by using string.join
string.join(",",EventList);
Related
In the following code , rating in generating error
string[] allLines = File.ReadAllLines(#"Ratings.csv");
var parsed = from line in allLines
let row = line.Split(';')
select new
{
UserId = row[0],
ItemId = row[1],
rating = row[3]
};
var Rating = parsed.Select(x => new AddRating (x.UserId, x.ItemId,x.rating));
client.Send(new Batch(Rating));
var detailViews = parsed.Select(x => new AddDetailView(x.UserId, x.ItemId,x.rating ));
The exception is telling you what the issue is. Your constructor is expecting doubles, and you're passing it strings. In order to fix it, you've gotta parse your string inputs into doubles.
The way your code is written, you'll have to change the way you're using the .Select statement in order to parse it in a decent error handling manner.
I'd suggest swapping the .Select for a foreach, then parsing each property, then instantiating your class.
foreach (var item in parsed)
{
double userId = 0;
double itemId = 0;
double rating = 0;
double.TryParse(item.UserId, out userId);
double.TryParse(item.ItemId, out itemId);
double.TryParse(item.rating, out rating);
var rating = new AddRating(userId, itemId, rating);
//**** do whatever you want with the new object
}
String st = "85.78";
Double db = Convert.ToDouble(st);
//Or With Error Hndler
try
{
string st = "85.78";
Double db = Convert.ToDouble(st);
}
catch (FormatException)
{
// Your error handler
}
I'm trying to test a form by submitting a combination of all values to see if it breaks. These are ComboBoxes that I have stored in an ExtraField class
public class ExtraField
{
public String Name = ""; //name of form key
public Dictionary<String, String> Options = new Dictionary<String, String>(); //Format: OptionText, Value
}
I have generated a list of these fields
List<ExtraField> efList = new List<ExtraField>();
I was thinking all possible combinations of these fields could be added to a string list that I can parse (I was thinking name=opt|name=opt|name=opt). I've provided an example of what would work below (where ExtraField list Count==3):
List<ExtraField> efList = new List<ExtraField>();
ExtraField f1 = new ExtraField();
f1.Name = "name1";
f1.Options.Add("text", "option1");
f1.Options.Add("text2", "option2");
f1.Options.Add("text3", "option3");
efList.Add(f1);
ExtraField f2 = new ExtraField();
f2.Name = "name2";
f2.Options.Add("text", "option1");
f2.Options.Add("text2", "option2");
f2.Options.Add("text3", "option3");
f2.Options.Add("text4", "option4");
efList.Add(f2);
ExtraField f3 = new ExtraField();
f3.Name = "name3";
f3.Options.Add("text2", "option1");
f3.Options.Add("text3", "option2");
f3.Options.Add("text4", "option3");
f3.Options.Add("text5", "option4");
f3.Options.Add("text6", "option5");
efList.Add(f3);
Should produce
name1=option1|name2=option1|name3=option1
name1=option1|name2=option1|name3=option2
name1=option1|name2=option1|name3=option3
name1=option1|name2=option1|name3=option4
name1=option1|name2=option1|name3=option5
name1=option1|name2=option2|name3=option1
name1=option1|name2=option2|name3=option2
name1=option1|name2=option2|name3=option3
name1=option1|name2=option2|name3=option4
name1=option1|name2=option2|name3=option5
name1=option1|name2=option3|name3=option1
name1=option1|name2=option3|name3=option2
name1=option1|name2=option3|name3=option3
name1=option1|name2=option3|name3=option4
name1=option1|name2=option3|name3=option5
name1=option1|name2=option4|name3=option1
name1=option1|name2=option4|name3=option2
name1=option1|name2=option4|name3=option3
name1=option1|name2=option4|name3=option4
name1=option1|name2=option4|name3=option5
name1=option2|name2=option1|name3=option1
...etc
All ExtraFields in the list need to have a value and I need all permutations in one format or another. It's a big list with a lot of permutations otherwise I'd do it by hand.
Well I did it... But I'm not proud of it. I'm sure there is a better way of doing it recursively. Hopefully this helps someone.
public List<String> GetFormPermutations(List<ExtraField> inList)
{
List<String> retList = new List<String>();
int[] listIndexes = new int[inList.Count];
for (int i = 0; i < listIndexes.Length; i++)
listIndexes[i] = 0;
while (listIndexes[inList.Count-1] < inList.ElementAt(inList.Count-1).Options.Count)
{
String cString = "";
//after this loop is complete. a line is done.
for (int i = 0; i < inList.Count; i++) {
String key = inList.ElementAt(i).Name;
Dictionary<String, String> cOptions = inList.ElementAt(i).Options;
String value = cOptions.ElementAt(listIndexes[i]).Value;
cString += key + "=" + value;
if (i < inList.Count - 1)
cString += "|";
}
retList.Add(cString);
listIndexes[0]++;
for(int i = 0; i < inList.Count -1; i++)
{
if (listIndexes[i] >= inList.ElementAt(i).Options.Count)
{
listIndexes[i] = 0;
listIndexes[i + 1]++;
}
}
}
return retList;
}
UPDATED ANSWER
So I managed to do it recursively. I haven't done this since college :D
Here's the whole class:
https://gist.github.com/Rastamas/8070ae7e1471d2183451a17bcf061376
PREVIOUS ANSWER BELOW
This goes through your list and adds the strings to a StringBuilder in the format you showed
foreach (var item in efList)
{
foreach (var option in item.Options)
{
stringBuilder.Append(String.Format("{0}={1}|", item.Name, option.Value));
}
stringBuilder.Remove(stringBuilder.Length - 1, 1);
stringBuilder.AppendLine();
}
Then you can just use stringBuilder.ToString() to get the whole list.
I get the datas from an textfile. The File itself is already inserted by ReadAllLines and converted into a string - this works fine for me and I checked the content with a MessageBox.
The Textfile looks like this (This is just 1 line from about thousand):
3016XY1234567891111111ABCDEFGHIJKabcdef+0000001029916XY1111111123456789ABCDEFGHIJKabcdef+00000003801
Now these are 2 records and I need 2 datas from every record.
The "XY Number" - these are the first 16 digits AFTER "16XY" (16XY is always the same value)
Value from the example: XY1234567891111111
The "Price" - that is the 11 digits value after the plus. The last 2 digits specify the amount of Cent.
Value from the example: 102,99$
I Need both of this datas to be in the same row in my Datagrid View and also for all other Datas in this textfile.
All I can imagine is to write a code, which searchs the string after "16XY" and counts the next 16 digits - the same with the Price which searchs for a "plus" and counts the next 11 digits. Just in this case I would need to ignore the first line of the file because there are about 10x"+".
I tried several possibilities to search and count for that values but without any success right now. Im also not sure how to get the datas into the specific Datagrid View.
This is all I have to show at the moment:
List<List<string>> groups = new List<List<string>>();
List<string> current = null;
foreach (var line in File.ReadAllLines(path))
{
if (line.Contains("") && current == null)
current = new List<string>();
else if (line.Contains("") && current != null)
{
groups.Add(current);
current = null;
}
if (current != null)
current.Add(line);
}
//array
string output = string.Join(Environment.NewLine, current.ToArray());
//string
string final = string.Join("", output.ToCharArray());
MessageBox.Show(output);
Thanks in advance!
Create a class or struct to hold data
public class Data
{
String XYValue { set; get; }
Decimal Price { set; get; }
}
Then the reading logic (You might need to add some more checks):
string decimalSeperator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
List<Data> results = new List<Data>();
foreach(string line in File.ReadAllLines(path).Skip(1))
{
if (line == null)
continue;
int indexOfNextXY = 0;
while (true)
{
int indexOfXY = line.IndexOf("16XY", indexOfNextXY) + "16XY".Length;
int indexOfPlus = line.IndexOf("+", indexOfXY + 16) + "+".Length;
indexOfNextXY = line.IndexOf("16XY", indexOfPlus);
string xyValue = line.Substring(indexOfXY - 2, 18); // -2 to get the XY part
string price = indexOfNextXY < 0 ? line.Substring(indexOfPlus) : line.Substring(indexOfPlus, indexOfNextXY - indexOfPlus);
string intPart = price.Substring(0, price.Length - 2);
string decimalPart = price.Substring(price.Length - 2);
price = intPart + decimalSeperator + decimalPart;
results.Add(new Data (){ XYValue = xyValue, Price = Convert.ToDecimal(price) });
if (indexOfNextXY < 0)
break;
}
}
var regex = new Regex(#"\+(\d+)(\d{2})16(XY\d{16})");
var q =
from e in File.ReadLines("123.txt")
let find = regex.Match(e)
where find.Success
select new
{
price = double.Parse(find.Groups[1].Value) + (double.Parse(find.Groups[2].Value) / 100),
value = find.Groups[3]
};
dataGridView1.DataSource = q.ToList();
If you need the whole text file as string, you can manipulate it with .Split method.
The action will look something like this:
var values = final.Split(new string[] { "16XY" }, StringSplitOptions.RemoveEmptyEntries).ToList();
List <YourModel> models = new List<YourModel>();
foreach (var item in values)
{
if (item.IndexOf('+') > 0)
{
var itemSplit = item.Split('+');
if (itemSplit[0].Length > 15 &&
itemSplit[1].Length > 10)
{
models.Add(new YourModel(itemSplit[0].Substring(0, 16), itemSplit[1].Substring(0, 11)));
}
}
}
And you will need some model
public class YourModel
{
public YourModel(string xy, string price)
{
float forTest = 0;
XYNUMBER = xy;
string addForParse = string.Format("{0}.{1}", price.Substring(0, price.Length - 2), price.Substring(price.Length - 2, 2));
if (float.TryParse(addForParse, out forTest))
{
Price = forTest;
}
}
public string XYNUMBER { get; set; }
public float Price { get; set; }
}
After that you can bind it to your gridview.
Given that the "data pairs" are variable each line (and can get truncated to the next line), it is best to use File.ReadAllText() instead. This will give you a single string to work on, eliminating the truncation issue.
var data = File.ReadAllText(path);
Define a model to contain your data:
public class Item {
public string XYNumber { get; set; }
public double Price { get; set; }
}
You can then use regular expressions to find matches and store them in a list:
var list = List<Item>();
var regex = new Regex(#"(XY\d{16})\w+\+(\d{11})");
var match = regex.Match(data);
while (match.Success) {
var ps = match.Group[1].Captures[0].Value.Insert(9, ".");
list.Add(new Item {
XYNumber = match.Group[0].Captures[0].Value,
Price = Convert.ToDouble(ps)
});
match = match.NextMatch();
}
The list can also be used as a data source to a grid view:
gridView.DataSource = list;
Consider employing the Split method. From the example data, I notice there is "16XY" between each value. So something like this:
var data = "3016XY1234567891111111ABCDEFGHIJKabcdef+0000001029916XY1111111123456789ABCDEFGHIJKabcdef+00000003801";
var records = data.Split(new string[] { "16XY" }, StringSplitOptions.RemoveEmptyEntries);
Given the example data this will return the following array:
[0]: "30"
[1]: "1234567891111111ABCDEFGHIJKabcdef+00000010299"
[2]: "1111111123456789ABCDEFGHIJKabcdef+00000003801"
Now it will be easier to count characters in each string and give them meaning in your code.
So we know valuable data is separated by +. Lets split it further and fill a Dictionary<string, double>.
var parsed = new Dictionary<string, double>(records.Length - 1);
foreach (var pairX in records.Skip(1))
{
var fields = pairX.Split('+');
var cents = double.Parse(fields[1]);
parsed.Add(fields[0], cents / 100);
}
// Now you bind to the GridView
gv.DataSource = parsed;
And your 'GridView` declaration should look like this:
<asp:GridView ID="gv" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="Key" HeaderText="ID" />
<asp:BoundField DataField="Value" HeaderText="Price" />
</Columns>
</asp:GridView>
I have a very complex problem. At least to me it is, since I am a beginner.
I have 2 List(string) lists.
One of them is filled with currency ISO codes. Second is their value. Both lists have 332 lines.
I want to compare a Console.ReadLine(); input with the currency ISO codes list.
If it is contained in the list to get it's row number.
Then get that row number and use it to get the same row from the value list.
Here is the code:
download = empty16.Replace(download, "");
StringBuilder sb1 = new StringBuilder();
for (int iaU = 0; iaU < download.Length; iaU++)
{
if (iaU%3 == 0)
sb1.Append('\n');
sb1.Append(download[iaU]);
}
string formDown = sb1.ToString();
List<string> formFin = formDown.Split('\n').ToList(); //This is the ISO list
List<string> l1st = new List<string>();
int iwNz = 0;
while (iwNz < intVal)
{
string sub = formIvx.Substring(iwNz);
//Console.WriteLine(sub);
l1st.Add(sub);
iwNz += intVal;
}
You want something like this:
string input = Console.ReadLine();
int index = formFin.IndexOf(input);
if(index != -1)
{
var value = valueList[index];
}
I am using this code in my Web Api to get data from a csv file, and plug that data into a Item List.
private List<Item> ietms = new List<Item>();
public ItemRepository()
{
string filename = HttpRuntime.AppDomainAppPath + "App_Data\\items.csv";
var lines = File.ReadAllLines(filename).Skip(1).ToList();
for (int i = 0; i < lines.Count; i++)
{
var line = lines[i];
var columns = line.Split('$');
//get rid of newline characters in the middle of data lines
while (columns.Length < 9)
{
i += 1;
line = line.Replace("\n", " ") + lines[i];
columns = line.Split('$');
}
//Remove Starting and Trailing open quotes from fields
columns = columns.Select(c => { if (string.IsNullOrEmpty(c) == false) { return c.Substring(1, c.Length - 2); } return string.Empty; }).ToArray();
items.Add(new Item()
{
Id = int.Parse(columns[0]),
Name = columns[1],
Description = columns[2],
Price = string.IsNullOrEmpty(columns[3].Trim()) ? null : (double?)double.Parse(columns[3]),
Weight = columns[8],
PhotoUrl = columns[7],
Category=columns[9]
});
}
}
In the csv file one of the columns/value is structured like this:
Groups>Subgroup>item
or in some cases
MajorGroup|Groups>Subgroup>item
How do I pull out only the first value before the > or |, so that I would get the value as Groups in the first case and MajorGroup in the second, and store it in the Category property in the Item List, which is now just set to the entire value in column 9 which would return the whole string "Groups>Subgroup>item".
Add the following line before calling "Add item"
var temp = columns[9].Split('|', '>');
Then assign the category as follows.
Category = temp[0];
Based on: MSDN String Method Documentation
Did you mean something like this?
string data = "MajorGroup|Groups>Subgroup>item";
string groupOrCategory;
if (data.Contains('|'))
{
groupOrCategory = data.Substring(0, data.IndexOf('|'));
}
else
{
groupOrCategory = data.Substring(0, data.IndexOf('>'));
}
Console.WriteLine(groupOrCategory);