I am using the following code in my .NET web service that gets its data form a CSV file.
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();
var temp = columns[5].Split('|', '>');
items.Add(new Item()
{
Id = int.Parse(columns[0]),
Name = columns[1],
Description = columns[2],
Category = temp[0]
});
}
}
This code gets a list of products from the CSV file along with its name, description etc. Each product belongs to either one or two categories : Category = temp[0].
Each product's category is found in a column of the csv file with it's data structured as such:
Groups>Subgroup>item, in which case, this product belongs to category "Groups".
The category column of a product may also be structured as:
MajorGroup|Groups>Subgroup>item, in which case this product belongs to category "MajorGroup".
Also, in many cases a product's category column may be structured as:
MajorGroup|Groups>Subgroup>item|SecondGroup, in which case this product belong to both the categories "MajorGroup" and "SecondGroup"
The code above that I am currently using does half the job. If a product has a category defined in the CSV file as MajorGroup|Groups>Subgroup>item|SecondGroup, it assigns it to category "MajorGroups" but not "SecondGroup".
This line var temp = columns[5].Split('|', '>'); gets the first value structured taht way and separated by a pipe and sets it as the product's category here Category = temp[0].
How do I fix this so that if the category is structured as MajorGroup|Groups>Subgroup>item|SecondGroup, with two categories, then it will show up in both categories.
How do I assign the product to one or more categories depending on the structure of the category column data.
This works for the most part, but how do I alter the code to check and assign for both categories?
Can I change this var temp = columns[5].Split('|', '>'); to get both teh first and the last value if it exists and assign both to Category = temp[0].
To get the second group values given the problem statement as specified you could do the following.
...
var temp = columns[5].Split('|', '>');
string categories= temp[0];
if (input.Count(x => x == '|') >= 2)
{
categories+= "," + temp.Last();
}
...
Category = categories;
Then one could get a list of Items that is assigned to a category by the following function:
static public IList<Item> GetProductsByCategory(string category, IList<Item> items)
{
return items.Where(x => x.Category.Split(',').Contains(category,StringComparer.OrdinalIgnoreCase)).ToList();
}
A much cleaner solution is to store the categories within the Item class as something that implements ILIST.
You should definitely use some CSV parser instead of doing this manually. There are too many potential problems and issues when parsing CSV manually that it is much easier and faster to use some existing tool like:
FileHelpers
Fast CSV Reader
Related
Well I have a list which is called employeeList. In the emoloyee Liste there are stored employees with some attributes like id, lastname ...
One of the attributes is Department. Now I want to create Radio Buttons with the Department. As there are more employees per department one department can appear several times but this I'd like to avoid. This is what I already got:
for (int i = 0; i < employeeList.Count(); i++)
{
panDepartments.Children.Add(new RadioButton() { Content = employeeList.ElementAt(i).Department.Distinct()});
}
Just filter the list before you iterate over it. One possibility would be LINQ (i.e. Distinct()) or just do the filtering yourself.
I think you can try something like this.
//First of all we need to get unique departments.
var departments = employeeList.Select(e => e.Department).Distinct();
//And after that we can create radio buttons and add them as children elements.
foreach(var dep in departments)
{
panDepartments.Children.Add(new RadioButton() { Content = dep });
}
//foreach loop can be replaced something like this if "panDepartments.Children"
//supports "AddRange" method
var radioBtns = departments.Select(d => new RadioButton() { Content = dep });
panDepartments.Children.AddRange(radioBtns);
I am automating some website and I got stuck on such a case. I have a list created, everything is great for me, it has 24 elements. These are products from the store, containing their picture, name, price, etc. But now I need to take two things from the first element and display in the console, namely name and price. Is anyone able to suggest something? I sit and thinks but nothing comes out. All I managed to do was send everything for 1 item.
I tried resolve that with some Linq but without success.
public List<string> ListOfElements()
{
var elements = new List<string>();
IReadOnlyCollection<IWebElement> listElements = _driver.FindElements(By.CssSelector(".category-list div[class='cat-prod-row js_category-list-item js_clickHashData js_man-track-event ']");
foreach (IWebElement element in listElements)
{
elements.Add(element.Text);
}
return elements;
}
public void DisplayFirstElement()
{
var firstElement = ListOfElements();
Console.WriteLine(firstElement[0]);
}
I want get name and price of first element and then assert that price for that is greater than 10.
You´re flattening all the elements properties into a single collection of strings. Thus you´re losing any relationship between those strings. It´s hard to say what the 22rd element within thhat list actually is: is it a price? A name? Something completey different? To which item does it actually belong?
Instead you should just return a list of entities and then print the properties of the very first entitity:
public List<IWebElement> ListOfElements()
{
var elements = new List<string>();
return listElements = _driver.FindElements(By.CssSelector(".category-list div[class='cat-prod-row js_category-list-item js_clickHashData js_man-track-event ']");
}
public void DisplayFirstElement()
{
var allElements = ListOfElements();
var firstElement = allElements.First();
Console.WriteLine("FirstName: " + firstElement.Name + " Price: " + firstElement.Price);
}
Of course this assumes your IWebElement has a Name- and a Price-property.
I am currently developing a program that should create invoices and add lines based on the selection of table.
This is my table (created using DevExpress):
These are future invoice lines that have a company ID as reference.
What I want to do with the future button 'Create invoices' is create 1 invoice per selected ID and add all of the selected lines to the invoicelines table.
My tables are:
Invoice
InvoiceID
CompanyID
InvoiceLines
ID
InvoiceID
Title
....
Based on my example picture, the result I would desire is:
2 invoices with each having 2 lines added
The problem is that I do not know how to handle this in my code.
I currently have:
private void btn_ExportToDB_ItemClick(object sender, ItemClickEventArgs e)
{
List<int> PWIDs = new List<int>();
List<int> distinct = new List<int>();
Dictionary<int, int> lines = new Dictionary<int, int>();
if (gridView.SelectedRowsCount > 0)
{
for (int i = gridView.SelectedRowsCount - 1; i >= 0; i--)
{
int rowHandle = gridView.GetSelectedRows()[i];
int PWID = int.Parse(gridView.GetRowCellValue(rowHandle, "pwID_PW").ToString());
PWIDs.Add(PWID);
lines.Add(rowHandle, PWID);
MessageBox.Show("customer id " + PWID);
distinct = PWIDs.Distinct().ToList();
}
foreach (int value in distinct)
{
}
}
}
I tried to do the following:
1- Create a dictionary in which I put the selected rowhandle + pwID.
2- After, I loop through my dictionary and select distinct pwID values (these are used for my invoices).
3- Hereafter, I'm stuck with my invoice lines, that I can't seem to add to my invoicelines table because I think my design on handling this problem is wrong.
How could I solve this in the most efficient way?
If you can return the entire ticket objects from the selection list in your screenshot then you could run a piece of code as below;
public List<Invoice> CreateInvoices(IEnumerable<Ticket> selectedTickets)
{
// Group tickets by company id
return selectedTickets.GroupBy(ticket => ticket.CompanyId)
// Convert grouping into new Invoice objects
.Select(g => new Invoice
{
// Build invoice object
CompanyId = g.Key,
// Build invoice lines
InvoiceLines = g.Select(line => new InvoiceLine() {Title = line.Title}).ToList()
}).ToList();
}
This shall return a IEnumerable of Invoices containing multiple InvoiceLines inside of each.
I have an ordered list ordered by two values. It contains a string, a TimeSpan and a integer. Its ordered by the the two first. I'll show you an example of what it contains:
E2801160600002066ED71483 09:36:37.6367671 1
E2801160600002066ED71483 09:36:38.1968231 1
E2801160600002066ED71483 09:36:38.8968931 2
E2801160600002066ED71483 09:36:39.4969531 2
E2801160600002066ED71483 09:36:40.2020236 2
E2801160600002066ED71493 09:36:37.6367671 2
E2801160600002066ED71493 09:36:38.3968431 2
E2801160600002066ED71493 09:36:39.0969131 1
The last integer refers to two antenas, number one is first antenna and number two is the second. It will always go in a direction, I mean if it goes first for the number one and later for the number two, it means the product is going outside. If it goes first for the number two and later for the number one, it means the product is going inside.
So I need to know how to iterate the list and compare the integer to know if the product is going outside or inside.
In the example the first product (string ends in 83) is going outside and the second product (string ends in 93) is going inside. So you know what I mean.
Assuming your model looks like so:
class Data
{
string ProductId {get; set;}
Timespan Timespan {get; set;}
int Antenna {get; set;}
}
With your sorted list...
List<Data> data = ...
...do the following with the help of Linq: First group it by product...
var productEntries = data.GroupBy(entry => entry.ProductId);
...then project the product groupings to a new list (IEnumerable, really) and determine whether the product is incoming our outgoing by checking if the first item of the group has the antenna ID 1 or 2.
var productDirections = productEntries.Select(
product => new
{
Id = product.Key,
IsIncoming = product.First().Antenna == 2
});
Afterwards you can iterate over the new list and check the IsIncoming boolean to get the direction of a product.
foreach (var product in productDirections)
{
if (product.IsIncoming)
handleIncoming(product.Key);
else
handleOutgoing(product.Key);
}
To Abbondanza, thanks for your help man
var productDirection = productEntries.Select(
product => new
{
Product = product.Key,
IsIncoming = product.First().antena == 2 && product.Last().antena == 1,
IsOutgoing = product.First().antena == 1 && product.Last().antena == 2,
StillInside = product.First().antena == 1
});
foreach (var product in productDirection)
{
if (product.IsIncoming)
{
// handle incoming products
Console.WriteLine("The product " + product.Product + " is incoming");
}
else if (product.IsOutgoing)
{
// handle outgoing products
Console.WriteLine("The product " + product.Product + " is outgoing");
}
else if (product.StillInside)
{
//handle still inside products
Console.WriteLine("The product " + product.Product + " is still inside");
}
else
{
//handle still outside products
Console.WriteLine("The product " + product.Product + " is still outside");
}
}
I am creating a Pie Chart and its name-value pair are being retrieved from the database.
how to read the row details in order to get the values and store it one property ?
public override void OnApplyTemplate()
{
Ram.DataContext = new List<UsageRAM>()
{ new UsageRAM() { name = "Available" , value =/*how to get the value here*/ },
new UsageRAM() { name = "Used" , value =/*how to get the value here*/ }};
base.OnApplyTemplate();
}
public class UsageRAM
{
public string name { get; set; }
public double value { get; set; }
}
EDIT
--Answer which worked for me--
using (DB db = new DB())
{
var row = (from c in db.UsageRAMs
orderby c.UsageRamID descending
select c).First();
Ram.DataContext = new List<UsageRAM>()
{ new UsageRAM() { name = "Available" , value = row.Available},
new UsageRAM() { name = "Used" , value = row.Used }};
If you're using EF, simply add a new model to your project and include the requried table(s) in this model. Then you can use the newly created Entities object to read your db values as follows:
var Rows = context.YourTableName.Where(YourCondition).ToArray();
You can then iterate over the Rows collection using foreach or something.
If you need to read values from a single row, you may want to use First instead of Where above. That will return a single object whose properties will map to your db fields and can directly be assigned in the example code you posted in the question.
EXAMPLE
Say your model's Entity class is named MyEntities and it contains the table UsageRam, which has two fields Available and Used. Then it will take the following code:
using(MyEntities e = new MyEntities)
{
var Row = e.MyTable.First(x => x.UsageRamID = **[ID]**);
MessageBox.Show("Available=" + Row.Available.ToString() + ",Used=" + Row.Used.ToString();
}
I have just shown values in message box, you can assign them to anything you want.
Another Example
using(MyEntities e = new MyEntities)
{
var Rows = e.MyTable.Where(x => x.UsageRamID > 10 && x.UsageRamID < 20);
foreach(var Row in Rows)
MessageBox.Show("Available=" + Row.Available.ToString() + ",Used=" + Row.Used.ToString();
}
EXAMPLE 3
The code in your updated post appears fine to me, though I do have some doubts about the db design, but given your table is indexed on RamUsageID column, this should give you correct results without much performance impact. I generally prefer lambada expressions over query, so I'd rather write it like:
db.RamUsage.OrderByDescending(x => x.RamUsageID).First()