Find within large list using Contains within Linq - c#

I have two large excel files. I am able to get the rows of these excel files into a list using linqtoexcel. The issue is that I need to use a string from one object within the first list to find if it is part of or contained inside another string within an object of the second list. I was trying the following but the process is taking to long as each list is over 70,000 items.
I have tried using an Any statement but have not be able to pull results. If you have any ideas please share.
List<ExcelOne> exOne = new List<ExcelOne>();
List<ExcelTwo> exTwo = new List<ExcelTwo>();
I am able to build the first list and second list and can verify there are objects in the list. Here was my thought of how I would work through the lists to find matching. Note that once I have found the matching I want to create a new class and add it to a new list.
List<NewFormRow> rows = new List<NewFormRow>();
foreach (var item in exOne)
{
//I am going through each item in list one
foreach (var thing in exTwo)
{
//I now want to check if exTwo.importantRow has or
//contains any part of the string from item.id
if (thing.importantRow.Contains(item.id))
{
NewFormRow adding = new NewFormRow()
{
Idfound = item.id,
ImportantRow = thing.importantRow
};
rows.Add(adding);
Console.WriteLine("added one");
}
}
If you know a quicker way around this please share. Thank you.

It's hard to improve this substring approach. The question is if you have to do it here. Can't you do it where you have filled the lists? Then you don't need this additional step.
However, maybe you find this LINQ query more readable:
List<NewFormRow> rows = exOne
.SelectMany(x => exTwo
.Where(x2 => x2.importantRow.Contains(x.id))
.Select(x2 => new NewFormRow
{
Idfound = x.id,
ImportantRow = x2.importantRow
}))
.ToList();

Related

C# Comparing if two lists have the same order of items (alphabetical)

I'm facing a huge problem with comparing two lists. I just made copy of my first list and I tried to sort it. The problem is, I want to compare my original list and sorted one to see if they have same alphabetical order. I hope I provided enough information for my problem.
Thanks in advance
public void VerifyDataPrijave(string username)
{
List<string> listaTekstova = new List<string>(); //initializing new, empty List
var kartice = Repo.Kartice.CreateAdapter<Unknown>(false).Find(".//div[class='_63fz removableItem _95l5']");
foreach (var kartica in kartice) {
var slika = kartica.Find(".//tag[tagname='img']")[0];
var ime = slika.Find("following-sibling::div")[0];
string text = ime.GetAttributeValue("InnerText").ToString(); //loop through profile cards and getting Names as InnerText in variable text
listaTekstova.Add(text); //adding those "texts" I just found to an empty list initialized before
List<string> novaListaTekstova = new List<string>(listaTekstova); //clone (copy) of the very first one list
novaListaTekstova.Sort(); //sorting that list alphabetically (I suppose, not sure)
}
}
You can use SequenceEqual to compare to IEnumerables. In your case you can do something like this once all sorting has been done:
var isEqual = novaListaTekstova.SequenceEqual(listaTekstova);

I'm using the property findelements with selenium and C#, but it keeps giving the same error

This is a part of the code that i was trying to use to get the respective elements, but it keeps giving me the following error:
System.Collections.ObjectModel.ReadOnlyCollection`1[OpenQA.Selenium.IWebElement]or
others identical
This is also shown in a datagridview, in her rows.
IList<IWebElement> ruas = Gdriver.FindElements(By.ClassName("search-title"));
String[] AllText = new String[ruas.Count];
int i = 0;
foreach (IWebElement element in ruas)
{
AllText[i++] = element.Text;
table.Rows.Add(ruas);
}
First thing is: as far as I understand the elements you are talking about are not contained in table. Its a list: <ul class="list-unstyled list-inline">... (considering the comment you left with site link)
If you want to find those elements you can use the code below:
var elements = driver.FindElements(By.CssSelector("ul.list-inline > li > a"));
// Here you can iterate though links and do whatever you want with them
foreach (var element in elements)
{
Console.WriteLine(element.Text);
}
// Here is the collection of links texts
var linkNames = elements.Select(e => e.Text).ToList();
Considering the error you get, I may assume that you are using DataGridView for storing collected data, which is terribly incorrect. DataGridView is used for viewing data in MVC application. There is no standard Selenium class for storing table data. There are multiple approaches for this, but I can't suggest you any because I don't know your what you are trying to achieve.
Here is how i answered my own question:
IList<string> all = new List<string>();
foreach (var element in Gdriver.FindElements(By.ClassName("search-title")))
{
all.Add(element.Text);
table.Rows.Add(element.Text);
}

C#: Generating a table from a .CSV that counts name (string) occurences in another table

I am importing a data table from a .csv file with headers, and this is no problem.
So let us call the file dt.csv.
One column header is named companyName.
But I need to create a new table where I, first of all, list all the companies from the first data table and count how many times each companyName does appear in the first table.
The first table can have anything from 500 to 5000 lines, but the number of different companies appearing will only be 15-50. The challenge is that I do not know the company names to expect in advance, so I cannot make a positive list to count against. I need the list to count against to be generated based on the content of column companyName (so that I do not get duplicates of the same name).
This code is C# but is largely pseudocode as I'm not certain of your approach to reading / writing the CSV file:
var seenCompanies = new List<string>();
foreach(var line in csvFile)
{
seenCompanies.Add(line.GetColumn("companyName"));
}
var companiesAndCounts =
seenCompanies
.GroupBy(s => s)
.Select(group => new { Name = group.Key, Count = group.Count()})
.ToList();
foreach(var group in companiesAndCounts)
{
outputFile.Write(group.Name + "," + group.Count);
}
This is pretty standard conceptually, all you're really doing is just counting the occurrences of each distinct company name and then writing that out.
You can adapt this to better suit your needs, but it should be enough to show how it can be approached.
You can also use System.Generics.Dictionary
//I used this list to test, you should replace "companies" with a list from you csv file
List<string> companies = new List<string>(){"c1","c2","c1","c4","c3","c3","c3","c2"};
Dictionary<string,int> numberOfAppearance = new Dictionary<string,int>();
foreach(string company in companies)
{
if(numberOfAppearance.ContainsKey(company))
numberOfAppearance[company]++;
else
numberOfAppearance.Add(company, 1);
}
//Now numberOfAppearance["companyName"] holds the number of appearances of the company named companyName in the list
I created a List to hold all the company names as I don't know how you store them from your csv file, but It should be easy to adapt.

Find a if filename does not exist in array of variable names

I have a list of zipped files that contains a ZipArchive and the zipped filename as a String. I also have a final list of filenames that I need to check with my List and if the files do not match with my final list of filenames they should be dumped from my zipped file list.
I under stand that may not be worded the best so let me try and explain with my code/pseudo code.
Here is my list:
List<ZipContents> importList = new List<ZipContents>();
Which has two parameters:
ZipArchive which is called ZipFile
String which is called FileName
filenames is the finale list of file names that I am trying to check my ZipContents list against.
Here is the start of what I am trying to do:
foreach (var import in importList)
{
var fn = import.FileName;
// do some kind of lookup to see if fn would be List<String> filenames
// If not in list dump from ZipContents
}
The commented out section is what I am unsure about doing. Would someone be able to help get me on the right track? Thanks!
EDIT 1
I know I did not say this originally but I think that LINQ would be the much cleaner route to take. I am just not positive how. I am assuming that using .RemoveAll(..) would be the way I would want to go?
Loop through importList in reverse and remove items when not found in filenames. Assuming you don't have too many items performance should be fine:
for (int i = importList.Count - 1; i >= 0; i--)
{
if (!filenames.Contains(importList[i].FileName))
{
importList.RemoveAt(i);
}
}
You can't remove items from the list using a foreach because it modifies the collection, but you can do it with the construct in my example.
You could do something like:
if (!filenames.Contains(fn)) {
importList.Remove(import);
}
Alternatively, I believe you could use Linq to simplify this logic into just one line.
Edit:
Yes, you can just create a new list of just the ones you want, like this:
var newImportList = importList.Where(il => filenames.Contains(il.FileName)).ToList();
You can do this in one line. Just use LINQ to re-establish your list:
var filenames = new List<string> {"file1", "file2"};
var zipcontents = new List<ZipContents>
{
new ZipContents {FileName = "file1"},
new ZipContents {FileName = "file2"},
new ZipContents {FileName = "file3"}
};
zipcontents = zipcontents.Where(z => filenames.Contains(z.FileName)).ToList();
//zipcontents contains only files that were in 'filenames'
Honestly, this is what LINQ was made for: querying data.

How to retrieve checkbox options and add to database using linq

I am attempting to add some checkbox options to my database via LINQ entities as one item. However the roadblock i run into is that i get an error trying to add these as into one variable to add to the db. Here is what i have so far:
public string GetSelectedItems(CheckBoxList control)
{
var items = new StringBuilder();
foreach (ListItem item in chbxRoomChange.Items)
{
if (item.Selected)
items.Append(string.Format("{0},", item.Text));
}
return items.ToString().TrimEnd(',');
}
adding to db:
var choices = GetSelectedItems(chbxRoomChange);
rc.preference = choices;
Based on the exception details you have posted then I suspect the column you are inserting into the database is too small to hold the data you are passing from your application.
Debug your app and see what length of the string returned by GetSelectedItems is and then compare that with the size of the column you are inserting into. I suspect you will find your string just won't fit and you need to increase it's size.
As a side note you could rewrite your method to use 1 line:
var choices = string.Join(",", chbxRoomChange.Items
.Cast<ListItem>()
.Where(li => li.Selected)
.Select(li => li.Text)
.ToArray());

Categories

Resources