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 have a string like this:
var str = "DAVID CORPORATION"
then i have a list of substrings that i dont want in the str.
var describers = new List<string> {"CORP", "INC", "LTD", "TECH", "ENGINEER", "LLC","MICROELE"};
then i split the str here into a list:
var strList = str.Split(' ').ToList();
now i want to remove all items of that list that contains the substrings in describers. I found this way to do it a million times all over the internet.
strList.RemoveAll(x => describers.Contains(x));
This does not work because all it does is check if the describers contain the whole word of the strList. I need it to work in reverse.
This doesn't work but its an algorithm of how i want it to work.
strList.RemoveAll(x => x.Contains(describers.Any()));
Cannot convert from 'bool' to 'string'
of course, but how to i remove the item in strList that contains the substring item from describers.
..and only in a linq.lamba. I am trying to stay away foreach/for/do loops.
You can do the following using Any:
strList.RemoveAll(x => describers.Any(d => x.Contains(d)));
I've converted cells in my excel range from strings to form a string list and have separated each item after the comma in the original list. I am starting to think I have not actually separated each item, and they are still one whole, trying to figure out how to do this properly so that each item( ie. the_red_bucket_01)is it's own string.
example of original string in a cell 1 and 2:
Cell1 :
the_red_bucket_01, the_blue_duck_01,_the green_banana_02, the orange_bear_01
Cell2 :
the_purple_chair_01, the_blue_coyote_01,_the green_banana_02, the orange_bear_01
The new list looks like this, though I'm not sure they are separate items:
the_red_bucket_01
the_blue_duck_01
the green_banana_02
the orange_bear_01
the_red_chair_01
the_blue_coyote_01
the green_banana_02
the orange_bear_01
Now I want to remove duplicates so that the console only shows 1 of each item, no matter how many there are of them, I can't seem to get my foreah/if statements to work. It is printing out multiple copies of the items, I'm assuming because it is iterating for each item in the list, so it is returning the data that many items.
foreach (Excel.Range item in xlRng)
{
string itemString = (string)item.Text;
List<String> fn = new List<String>(itemString.Split(','));
List<string> newList = new List<string>();
foreach (string s in fn)
if (!newList.Contains(s))
{
newList.Add(s);
}
foreach (string combo in newList)
{
Console.Write(combo);
}
You probably need to trim the strings, because they have leading white spaces, so "string1" is different from " string1".
foreach (string s in fn)
if (!newList.Contains(s.Trim()))
{
newList.Add(s);
}
You can do this much simpler with Linq by using Distinct.
Returns distinct elements from a sequence by using the default
equality comparer to compare values.
foreach (Excel.Range item in xlRng)
{
string itemString = (string)item.Text;
List<String> fn = new List<String>(itemString.Split(','));
foreach (string combo in fn.Distinct())
{
Console.Write(combo);
}
}
As mentioned in another answer, you may also need to Trim any whitespace, in which case you would do:
fn.Select(x => x.Trim()).Distinct()
Where you need to contain keys/values, its better to use Dictionary type. Try changing code with List<T> to Dictionary<T>. i.e.
From:
List<string> newList = new List<string>();
foreach (string s in fn)
if (!newList.Containss))
{
newList.Add(s);
}
to
Dictionary<string, string> newList = new Dictionary<string, string>();
foreach (string s in fn)
if (!newList.ContainsKey(s))
{
newList.Add(s, s);
}
If you are concerned about the distinct items while you are reading, then just use the Distinct operator like fn.Distinct()
For processing the whole data, I can suggest two methods:
Read in the whole data then use LINQ's Distinct operator
Or use a Set data structure and store each element in that while reading the excel
I suggest that you take a look at the LINQ documentation if you are processing data. It has really great extensions. For even more methods, you can check out the MoreLINQ package.
I think your code would probably work as you expect if you moved newList out of the loop - you create a new variable named newList each loop so it's not going to find duplicates from earlier loops.
You can do all of this this more concisely with Linq:
//set up some similar data
string list1 = "a,b,c,d,a,f";
string list2 = "a,b,c,d,a,f";
List<string> lists = new List<string> {list1,list2};
// find unique items
var result = lists.SelectMany(i=>i.Split(',')).Distinct().ToList();
SelectMany() "flattens" the list of lists into a list.
Distinct() removes duplicates.
var uniqueItems = new HashSet<string>();
foreach (Excel.Range cell in xlRng)
{
var cellText = (string)cell.Text;
foreach (var item in cellText.Split(',').Select(s => s.Trim()))
{
uniqueItems.Add(item);
}
}
foreach (var item in uniqueItems)
{
Console.WriteLine(item);
}
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.
I have a links that the sub category got repeated a bunch of times. Also only want to keep the repeating if they are in a certain list. But also keep the last part of the link
About
Video
Example1
Example2
www.example.com/About/About/Videos/Videos/Videos/Featured/5-great-videos
should be
www.example.com/about/videos/5-great-videos
Any help?
How about this one, using LINQ
string str = "www.example.com/About/About/Videos/Videos/Videos/Featured/5-great-videos";
var result = str.Split('/').GroupBy(x=>x).Select(x=>x.Key).Aggregate((a,b)=>a+"/"+b);
In case you prefer not using linq:
string url = "www.example.com/About/About/Videos/Videos/Videos/Featured/5-great-videos";
List<string> urlList = new List<string>();
foreach (string urlToken in url.Split('/'))
if (!urlList.Contains(urlToken)) urlList.Add(urlToken);
url = String.Join("/", urlList.ToArray());