Error : System.Collections.Generic.List`1[System.String] [duplicate] - c#

This question already has an answer here:
System.Collections.Generic.List <string>' does not contain a definition for 'equals' [closed]
(1 answer)
Closed 6 years ago.
I have a query that contains hexadecimal codes and when there is a hexadecimal code I want to apply a background-color to the previous data in my table, but it's written
background-color:System.Collections.Generic.List`1[System.St‌​ring]
to each line in my source code.
Here is my code :
<tr>
#{
int nbItems = ViewBag.listDonnees.Count;
var hashCodes = new List<String>() { "#FFFFFF", "#FFD700", "#FF6347" };
for (int cpt = 0; cpt < nbItems; cpt++)
{
string colorcode = string.Empty;
if (cpt + 1 < nbItems)
{
var mylist = (IEnumerable < dynamic >) ViewBag.listDonnees[cpt];
colorcode = mylist.FirstOrDefault(s => hashCodes.Contains(s));
}
if (colorcode != string.Empty)
{
<td style="background-color:#ViewBag.listDonnees[cpt+1]">colorcode</td>
}
else
{
var str = String.Join(",", ViewBag.listDonnees[cpt]);
<td>str</td>
}
cpt++;
}
}
</tr>
And I would like replace "colorcode" by the current data and listDonnees is a List < List < string > >
My model :
dac = new SqlDataAdapter();
dac.SelectCommand = cmd1;
dsp = new DataSet();
dac.Fill(dsp, "donnees");
List<List<string>> listDonnees = new List<List<string>>();
foreach (DataRow row in dsp.Tables["donnees"].Rows)
{
List<string> l = new List<string>();
for (int i = 0; i < row.ItemArray.Length; i++)
{
l.Add(row[i].ToString());
}
listDonnees.Add(l);
}
list.Add("donnees", listDonnees);
My Controller :
public ActionResult AfficheRspic002(string Tdate_d, string Ddl_fampic, string Ddl_donnee, string Ddl_detail, string Ddl_caracteristique, string Ddl_poste, string Ddl_ilot, string Ddl_nposte, string Ddl_atelier, string Ddl_tposte)
{
Dictionary<string, object> list = model.getPICv2(Tdate_d,Ddl_fampic, Ddl_donnee, Ddl_detail, Ddl_caracteristique, Ddl_poste, Ddl_ilot, Ddl_nposte, Ddl_atelier, Ddl_tposte);
ViewBag.listEntete = list["entete"];
ViewBag.listJO = list["jo"];
ViewBag.listPrevision = list["prevision"];
ViewBag.listCommandeEt = list["commande"];
ViewBag.listDonnees = list["donnees"];
return PartialView();
}
Thank you in advance for your help

As you mentioned
listDonnees is a List < List < string > >
then of course, #ViewBag.listDonnees[cpt+1] will be list of string. You should store colorcode in ViewBag, not list of colorcode.
May be if you post how you are selecting color from list then we can give you more concrete answer.

Related

How to assign data from CSV into Object [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
so far I have this one which works really good.
private static MovieItem readCSV(string path)
{
var yourData = File.ReadAllLines(path)
.Skip(1)
.Select(x => x.Split(';'))
.Select(x => new Movie
{
GUID = x[0],
Title = x[1],
ISBN = x[2],
CreatedTime = DateTime.Now,
AuthorInformation = new AuthorInformation()
{
Id = Guid.NewGuid().ToString(),
Name = x[4],
Address = x[5],
Age = x[6]
}
}).ToArray();
return yourData[0];
}
My question is, is there a better way to assign the object?
So far I have like GUID = x[0], Title = x[1] and so on... it's not good because the header in the first row can change, so I want to be flexible.
Is there a way to assign e.g. GUID to the CSV header named GUID?
Like looking for the header name and if it is equal GUID, assign the content to GUID?
CSV File:
I've commented your question that already but here's a sample code:
1- Make a class and name it "Book" or whatever convenient. It's fields would be GUID, Title, ISBN, etc..
public class Book //I'm showing only one field of the class
{
private string title;
public string Title { get; set;}
public Book() {}
}
2-Read your CSV file onetime where you will read the first line only and split it to a string[] array -your splitter is ";"- and store the index of each field to a variable (Switch statement would be very helpful here)
public struct Headers //use it to store the index of each field in the file only title is shown here
{
public int title;
}
string[] rowSplitter = new string[] { "\r\n" };
string[] colSplitter = new string[] { ";" };
//Inside a method for reading the file use the following code
string[] csvData = File.ReadAllText(csvFile).Split(rowSplitter, StringSplitOptions.RemoveEmptyEntries);
string[] headerRow = csvData [0].Split(colSplitter, StringSplitOptions.None);
Headers column = new Headers();
for (int i = 0; i < headerRow.Length; i++)
{
switch (headerRow[i].ToLower())
{
case "title":
column.title = i;
break;
}
}
3- Use a loop to go through all the lines, Split by ";" again, and inside this loop instantiate a Book() object with corresponding data cuz now you know the index of each data item -the variables I mentioned.
for (int i = 1; i < csvData.Length; i++)
{
string[] currentRow = csvData[i].Split(colSplitter, StringSplitOptions.None);
Book bookItem = new Book();
bookItem.Title = currentRow[column.title];
//Here you can do whatever you like with this bookItem on-the-fly or if you want to keep it to the end of your code add it to a list.
}
//reading all the lines(rows) from the file.
string[] rows = File.ReadAllLines(Directory.GetFiles(#"D:\CSV\test.csv"));
DataTable dtData = new DataTable();
string[] rowValues = null;
DataRow dr = dtData.NewRow();
//Creating columns
if (rows.Length > 0)
{
foreach (string columnName in rows[0].Split(','))
dtData.Columns.Add(columnName.Replace(" ", "").ToLower());
}
//Creating row for each line.(except the first line, which contain column names)
for (int row = 1; row < rows.Length; row++)
{
rowValues = rows[row].Split(',');
dr = dtData.NewRow();
dr.ItemArray = rowValues;
dtData.Rows.Add(dr);
}

Trying to get all possible combinations from an unknown number of list of strings

Given a list of lists I am looking to create all possible combinations.
Example:
I have a list which holds 3 lists
List 1: Apple, Banana, Pear
List 2: Bed, Chair
List 3: Ben, Bob, Carl, Phil
From this I would expect to end up with a List of combinations
Apple_Bed_Ben
Apple_Bed_Bob
Apple_Bed_Carl
Apple_Bed_Phil
Apple_Chair_Ben
Apple_Chair_Bob
Apple_Chair_Carl
Apple_Chair_Phil
Banana_Bed_Ben
Banana_Bed_Bob
...
I don't know if I am missing something but I have been going in circles for hours now.
If I knew there would only ever be three lists I know I could just use nested for loops going through building the combination string but here there could be any number of lists.
Can anyone point me in the right direction to get this done?
This is what i currently have:
public class ChildrenNames
{
public string parentName;
public int numberOfNames;
public List<string> childrenNames = new List<string>();
}
public class Combination
{
public bool selected = true;
public string name;
}
List<Combination> GetAllCombinations()
{
List<Combination> allCombinations = new List<Combination>();
List<ChildrenNames> listOfChildren = new List<ChildrenNames>();
//Create list of children names for each parent object
for (int p = 0; p < parentObjects.Count; p++)
{
ChildrenNames cn = new ChildrenNames();
for (int c = 0; c < parentObjects[p].transform.childCount; c++)
cn.childrenNames.Add(parentObjects[p].transform.GetChild(c).name);
cn.parentName = parentObjects[p].name;
cn.numberOfNames = cn.childrenNames.Count;
listOfChildren.Add(cn);
}
for (int l = 0; l < listOfChildren.Count; l++)
{
for (int c = 0; c < listOfChildren[l].numberOfNames; c++)
{
if (l == 0)
{
for (int p = 0; p < listOfChildren.Count; p ++)
{
Combination combination = new Combination();
combination.name = listOfChildren[l].childrenNames[c];
allCombinations.Add(combination);
}
}
else
{
for (int i = 0; i < allCombinations.Count; i++)
allCombinations[i].name += "_" + listOfChildren[l].childrenNames[c];
}
}
}
return allCombinations;
}
This creates the correct number of combinations but for example throws out
Apple_Bed_Chair_Ben_Bob_Carl_Phil
I understand why this is happening but not how I can change this to get the expected result.
You need to keep track of the column for each of the lists in order for it to work properly.
public List<string> ZipStringLists(params List<string>[] lists)
{
var columnNo = new int[lists.Length];
var resultingList = new List<string>();
var stringBuilder = new StringBuilder();
while (columnNo[0] < lists[0].Count)
{
// Combine the items into one: Apple + Banana + Pear = AppleBananaPear
for (int i = 0; i < lists.Length; i++)
{
var listElement = lists[i];
// columnNo[i] contains which column to write out for the individual list
stringBuilder.Append(listElement[columnNo[i]]);
}
// Write out the result and add it to a result list for later retrieval
var result = stringBuilder.ToString();
resultingList.Add(result);
Console.WriteLine(result);
stringBuilder.Clear();
// We increment columnNo from the right to the left
// The next item after AppleBedBen is AppleBedBob
// Overflow to the next column happens when a column reaches its maximum value
for (int i = lists.Length - 1; i >= 0; i--)
{
if (++columnNo[i] == lists[i].Count
&& i != 0 /* The last column overflows when the computation finishes */)
{
// Begin with 0 again on overflow and continue to add to the next column
columnNo[i] = 0;
}
else
{
// No overflow -> stop
break;
}
}
}
return resultingList;
}
Usage:
List<string> list1 = new List<string> { "Apple", "Banana", "Pear" };
List<string> list2 = new List<string> { "Bed", "Chair" };
List<string> list3 = new List<string> { "Ben", "Bob", "Carl", "Phil" };
ZipStringLists(list1, list2, list3);
You could use a fairly generic solution that accepts any number of lists to incrementally build up the combinations. It's short, though not necessarily as optimal as other solutions as it builds intermediate lists:
public List<string> FindCombinations(params List<string>[] lists)
{
List<string> combinations = lists[0];
for (int i = 1; i < lists.Length; i++)
{
List<string> newCombinations = new List<string>(combinations.Count * lists[i].Count);
combinations.ForEach(s1 => lists[i].ForEach(s2 => newCombinations.Add($"{s1}_{s2}")));
combinations = newCombinations;
}
return combinations;
}
Usage:
List<string> combinations = FindCombinations(list1, list2, list3, list4, list5...)

Searching for a string in a string

Dear stackoverflow members,
I have this string:
string data = "1Position1234Article4321Quantity2Position4323Article3323Quantity";
I want to search for the values where the "keyword" is Position. In this case I want to get back 1 and 2. Each value is "indexed" with its own "keyword". So the value 1 in this string has the Position seperator. The value 1234 has the Article seperator and the value 4321 has the Quantity seperator.
I need a way to search through the string and want to get all positions, articles and quantitys back. Without the keywords.
Output shout be:
string[] position = {"1", "2"};
string[] article = {"1234", "4323"};
string[] quantity = {"4321", "3323"};
Hopefully some can help me here.
Thanks!
This is q quick solution I've come up with in LinqPad:
void Main()
{
string data = "1Position1234Article4321Quantity2Position4323Article3323Quantity";
var Articles = Indices(data, "Article").Dump("Articles: ");
var Posistions = Indices(data, "Position").Dump("Positions :");
var Quantities = Indices(data, "Quantity").Dump("Quantities :");
}
// Define other methods and classes here
public List<int> Indices(string source, string keyword)
{
var results = new List<int>();
//source: http://stackoverflow.com/questions/3720012/regular-expression-to-split-string-and-number
var temp = Regex.Split(source, "(?<Alpha>[a-zA-Z]*)(?<Numeric>[0-9]*)").ToList().Where (r => !String.IsNullOrEmpty(r)).ToList();
//select the list with index only where key word matches
var indices = temp.Select ((v,i) => new {index = i, value = v})
.Where (t => t.value == keyword);
foreach (var element in indices)
{
int val;
//get previous list entry based on index and parse it
if(Int32.TryParse(temp[element.index -1], out val))
{
results.Add(val);
}
}
return results;
}
Output:
Here's a possible algorithm:
Run trough the list and take each number / keyword.
Put them in a dictionary with key "keyword", value a list with all "numbers".
Iterate the dictionary and print they key + its values.
Below snippet can use to get the output like what you expected.
string data = "1Position1234Article4321Quantity2Position4323Article3323Quantity";
StringBuilder sb = new StringBuilder();
StringBuilder sbWord = new StringBuilder();
bool isDigit = false;
bool isChar = false;
Dictionary<int, string> dic = new Dictionary<int, string>();
int index = 0;
for (int i = 0; i < data.Length; i++)
{
if (char.IsNumber(data[i]))
{
isDigit = true;
if (isChar)
{
dic.Add(index, sb.ToString() + "|" + sbWord.ToString());
index++;
isChar = false;
sb.Remove(0, sb.Length);
sbWord.Remove(0, sbWord.Length);
}
}
else
{
isDigit = false;
isChar = true;
sbWord.Append(data[i]);
}
if (isDigit)
sb.Append(data[i]);
if (i == data.Length - 1)
{
dic.Add(index, sb.ToString() + "|" + sbWord.ToString());
}
}
List<string> Position = new List<string>();
List<string> Article = new List<string>();
List<string> Quantity = new List<string>();
if (dic.Count > 0)
{
for (int i = 0; i < dic.Count; i++)
{
if (dic[i].Split('|')[1] == "Position")
Position.Add(dic[i].Split('|')[0]);
else if (dic[i].Split('|')[1] == "Article")
Article.Add(dic[i].Split('|')[0]);
else
Quantity.Add(dic[i].Split('|')[0]);
}
}
string[] Position_array = Position.ToArray();
string[] Article_array = Article.ToArray();
string[] Quantity_array = Quantity.ToArray();
Try this simple solution.
class StrSplit{
public static void main(String args[]){
int i;
String str = "1Position1234Article4321Quantity2Position4323Article3323Quantity";
String pattern= "(?<=Position)|(?<=Article)|(?<=Quantity)";
String[] parts = str.split(pattern);
List<String> Position = new ArrayList<String>();
List<String> Article = new ArrayList<String>();
List<String> Quantity = new ArrayList<String>();
for( i=0;i<parts.length;i++)
{
pattern="Position";
String[] subParts;
if(parts[i].contains(pattern))
{
subParts = parts[i].split(pattern);
Position.add(subParts[0]);
}
pattern="Article";
if(parts[i].contains(pattern))
{
subParts = parts[i].split(pattern);
Article.add(subParts[0]);
}
pattern="Quantity";
if(parts[i].contains(pattern))
{
subParts = parts[i].split(pattern);
Quantity.add(subParts[0]);
}
}
System.out.println("Position:");
for(i = 0; i < Position.size(); i++) {
System.out.println(Position.get(i));
}
System.out.println("Article:");
for(i = 0; i < Article.size(); i++) {
System.out.println(Article.get(i));
}
System.out.println("Quantity:");
for(i = 0; i < Quantity.size(); i++) {
System.out.println(Quantity.get(i));
}
}
}
Output:
Position:
1
2
Article:
1234
4323
Quantity:
4321
3323

Two stringlists and foreach

My WebAPI receives two strings, one containing the display values (names), one containing the hidden values (emails).
Before, it only received one string, over which it used a foreach, and I am unsure how to get it to work with two, how to fill "name" from "nameslist":
[System.Web.Http.HttpGet]
public AjaxAnswer BatchUserCreate(string email, string names) {
string[] emaillist = email.Split('\n');
string[] nameslist = names.Split('\n');
foreach(string email in emaillist) {
db.AddParameter("#email",email);
db.AddParameter("#name",name);
int newId = db.ExecuteScalar(userInsQuery);
}
return new AjaxAnswer(newId);
}
Zip the two lists together
var nameEmailPairs = emaillist.Zip(namelist, (email,name)=>new{email,name});
You can then foreach over that, which will have items with a name and an email.
If you have a guarantee that these lists are in same order - use plain for loop:
for(int i=0; i<emaillist.Length; i++) {
string email = emaillist[i];
string name = namelist[i];
...
Or you can use LINQ with Zip:
var records = emaillist.Zip(namelist, (email, name) => new {email, name});
foreach(var r in records) {
string email = r.email;
string name = r.name;
...
You should use a for loop instead, something like this could help:
[System.Web.Http.HttpGet]
public AjaxAnswer BatchUserCreate(string email, string names) {
string[] emaillist = email.Split('\n');
string[] nameslist = names.Split('\n');
for(int i = 0; i!=emaillist.Length; ++i) {
db.AddParameter("#email", emaillist[i]);
db.AddParameter("#name", nameslist.Length > i ? nameslist[i] : "No name");
int newId = db.ExecuteScalar(userInsQuery);
}
return new AjaxAnswer(newId);
}
If the length of both arrays (emaillist & nameslist) is equal, you should use a for loop instead of a foreach loop:
[System.Web.Http.HttpGet]
public AjaxAnswer BatchUserCreate(string email, string names) {
string[] emaillist = email.Split('\n');
string[] nameslist = names.Split('\n');
for(int i = 0; i < emaillist.Length; i++) {
db.AddParameter("#email",emaillist[i]);
db.AddParameter("#name",namelist[i]);
int newId = db.ExecuteScalar(userInsQuery);
}
return new AjaxAnswer(newId);
}
try this work around hope it will help
for(int i =0 ; i< emaillist .count; i++)
{
db.AddParameter("#email",emaillist[i]);
db.AddParameter("#name",nameslist[i]);
int newId = db.ExecuteScalar(userInsQuery);
}
Try changing foreach loop to for loop:
[System.Web.Http.HttpGet]
public AjaxAnswer BatchUserCreate(string email, string names) {
string[] emaillist = email.Split('\n');
string[] nameslist = names.Split('\n');
// You should declare "newId" somewhere here
// if you want to return it via "new AjaxAnswer(newId)"
int newId = 0;
// if emaillist and nameslist have diffrent lengths
// let's take minimal length
int n = Math.Min(nameslist.Length, emaillist.Length);
for (int i = 0; i < n; ++i) {
db.AddParameter("#email", emaillist[i]);
db.AddParameter("#name", nameslist[i]);
newId = db.ExecuteScalar(userInsQuery);
}
return new AjaxAnswer(newId);
}

List sorting by multiple parameters

I have a .csv with the following headers and an example line from the file.
AgentID,Profile,Avatar,In_Time,Out_Time,In_Location,Out_Location,Target_Speed(m/s),Distance_Traveled(m),Congested_Duration(s),Total_Duration(s),LOS_A_Duration(s),LOS_B_Duration(s),LOS_C_Duration(s),LOS_D_Duration(s),LOS_E_Duration(s),LOS_F_Duration(s)
2177,DefaultProfile,DarkGreen_LowPoly,08:00:00,08:00:53,East12SubwayportalActor,EWConcourseportalActor,1.39653,60.2243,5.4,52.8,26.4,23,3.4,0,0,0
I need to sort this .csv by the 4th column (In_time) by increasing time ( 08:00:00, 08:00:01) and the 6th (In_Location) by alphabetical direction (e.g. East, North, etc).
So far my code looks like this:
List<string> list = new List<string>();
using (StreamReader reader = new StreamReader("JourneyTimes.csv"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
line.Split(',');
list.Add(line);
}
I read in the .csv and split it using a comma (there are no other commas so this is not a concern). I then add each line to a list. My issue is how do I sort the list on two parameters and by the headers of the .csv.
I have been looking all day at this, I am relatively new to programming, this is my first program so I apologize for my lack of knowledge.
You can use LINQ OrderBy/ThenBy:
e.g.
listOfObjects.OrderBy (c => c.LastName).ThenBy (c => c.FirstName)
But first off, you should map your CSV line to some object.
To map CSV line to object you can predefine some type or create it dynamically
from line in File.ReadLines(fileName).Skip(1) //header
let columns = line.Split(',') //really basic CSV parsing, consider removing empty entries and supporting quotes
select new
{
AgentID = columns[0],
Profile = int.Parse(columns[1]),
Avatar = float.Parse(columns[2])
//other properties
}
And be aware that like many other LINQ methods, these two use deferred execution
You are dealing with two distinct problems.
First, ordering two columns in C# can be achieved with OrderBy, ThenBy
public class SpreadsheetExample
{
public DateTime InTime { get; set; }
public string InLocation { get; set; }
public SpreadsheetExample(DateTime inTime, string inLocation)
{
InTime = inTime;
InLocation = inLocation;
}
public static List<SpreadsheetExample> LoadMockData()
{
int maxMock = 10;
Random random = new Random();
var result = new List<SpreadsheetExample>();
for (int mockCount = 0; mockCount < maxMock; mockCount++)
{
var genNumber = random.Next(1, maxMock);
var genDate = DateTime.Now.AddDays(genNumber);
result.Add(new SpreadsheetExample(genDate, "Location" + mockCount));
}
return result;
}
}
internal class Class1
{
private static void Main()
{
var mockData = SpreadsheetExample.LoadMockData();
var orderedResult = mockData.OrderBy(m => m.InTime).ThenBy(m => m.InLocation);//Order, ThenBy can be used to perform ordering of two columns
foreach (var item in orderedResult)
{
Console.WriteLine("{0} : {1}", item.InTime, item.InLocation);
}
}
}
Now you can tackle the second issue of moving data into a class from Excel. VSTO is what you are looking for. There are lots of examples online. Follow the example I posted above. Replace your custom class in place of SpreadSheetExample.
You may use a DataTable:
var lines = File.ReadAllLines("test.csv");
DataTable dt = new DataTable();
var columNames = lines[0].Split(new char[] { ',' });
for (int i = 0; i < columNames.Length; i++)
{
dt.Columns.Add(columNames[i]);
}
for (int i = 1; i < lines.Length; i++)
{
dt.Rows.Add(lines[i].Split(new char[] { ',' }));
}
var rows = dt.Rows.Cast<DataRow>();
var result = rows.OrderBy(i => i["In_time"])
.ThenBy(i => i["In_Location"]);
// sum
var sum = rows.Sum(i => Int32.Parse(i["AgentID"].ToString()));

Categories

Resources