I have a list of a tags. I want to get an a tag which contains a string.
I used the below code and everything work fine.
string mainLink = "";
List<HtmlNode> dlLink = new List<HtmlNode>();
dlLink = doc.DocumentNode.SelectNodes("//div[#class='links']//a").ToList();
foreach (var item in dlLink) {
if (item.Attributes["href"].Value.Contains("prefile"))
{
mainLink = item.Attributes["href"].Value;
}
}
but I want to write a simple code
var dlLink = doc.DocumentNode.SelectNodes("//div[#class='link']//a").ToList().Where(x => x.Attributes["href"].Value.Contains("prefile")).ToList().ToString();
But it does not work and I get nothing.
Your foreach is setting mainLink string, but your linq chain is using ToString on a List result.
Converting your code, you will have something like this:
mainLink = doc.DocumentNode.SelectNodes("//div[#class='links']//a")
.Where(item => item.Attributes["href"].Value.Contains("prefile"))
.Select(item => item.Attributes["href"].Value)
.Last();
I used Select to get only the href values, and getting the last as your foreach did, maybe you need to validate this last step, use a LastOrDefault, First, etc.
You can also use the Last or First instead of the Where condition:
mainlink = doc.DocumentNode.SelectNodes("//div[#class='links']//a")
.Last(item => item.Attributes["href"].Value.Contains("prefile"))
.Attributes["href"].Value;
Related
Please help me to fix this issue. My dropdown list looks something like this mentioned below.
Client
Contractor,Contractor,Contractor,Manager
Contractor,Manager
Manager
Operator
Viewer
I want to remove the duplicates and my output should be like :
Client
Contractor
Manager
Operator
Viewer
This is my code mentioned below:
Property:
public List<string> TeamRoleNames => TeamRoleUids.Select(MainRoles.GetRoleName).ToList();
Display Method:
{
result += " ; TeamRoleNames=" + this.TeamRoleNames;
}
GetRole Method:
{
string roleName;
if (RoleNameByUid.TryGetValue(roleUid, out roleName))
{
return roleName;
}
return null;
}
I have tried with Distinct Method mentioned below, But did not work like the output what I wanted!
public List<string> TeamRoleNames => TeamRoleUids.Select(MainRoles.GetRoleName).Distinct().ToList();
How can I fix this? Can anyone help?
Having elements comma separated require you to split them first to have an homogenous collection then do the distinct
// get the comma separated values out as 1 value each
// for that you can use split, remove empty and select many
// which will return as a single level list (flat)
var result = TeamRoleUids.SelectMany(o => o.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)).Distinct().ToList();
Consider converting the list to a set (hashset) since sets as a data structure doesn't allow duplicates.
More about hashsets form official documentation.
So, the solution would be similar to the following:
var hashSet = new HashSet<YourType>(yourList);
example:
var hashSet = new HashSet<string>(TeamRoleUids);
then converting it back toList() will remove duplicates.
If you have already tried Distinct and it hasn't worked, then you could do the following;
Split your string list to a List<string>
List<string> result = TeamRoleNames.Split(',').ToList();
Then when you're adding them to the dropdwon, check to see if the role is already in the dropdown. If so, move on, else add to the dropdown.
So something like
foreach(var role in this.TeamRoleNames)
{
if(!result.contains(role))
result += " ; TeamRoleNames=" + role;
}
You can use SelectMany to flatten a enumeration containing a nested enumeration. Here, we create the nested enumeration by splitting the string at the commas:
string[] input = {
"Client",
"Contractor,Contractor,Contractor,Manager",
"Contractor,Manager",
"Manager",
"Operator",
"Viewer"
};
var roles = input
.SelectMany(r => r.Split(','))
.Distinct()
.OrderBy(r => r)
.ToList();
foreach (string role in roles) {
Console.WriteLine(role);
}
prints
Client
Contractor
Manager
Operator
Viewer
I have a text file which is being read using File.ReadLines(filepath). It's filled with first and last names delimited using a :. Is there a way using LINQ in which I would be able to access the first and last name in the foreach loop for the returned datatype?
// john:doe
// david:smith
// michael:rogers
var Names = File.ReadLines(filepath)
.Select(line => line.Split(':'));
foreach (var list in Names)
listbox1.Items.Add(list); //(first name) before :
listbox2.Items.Add(list); //(last name) after :
Well, you're almost there. All you're missing is to get the firstName from the first item in the array and the last name in the second item.
foreach (var list in Names)
{
listbox1.Items.Add(list[0]); //(first name) before :
listbox2.Items.Add(list[1]); //(last name) after :
}
list[0] is the first and list[1] the second
listbox1.DataSource = Names.Select(a => a[0]).ToArray();
listbox2.DataSource = Names.Select(a => a[1]).ToArray();
Based on your example, I assume it is not multicolumn ListBox.
Use SelectMany to flatten the hierarchy after splits.
listbox1.DataSource = File.ReadLines(filepath)
.SelectMany(line=>line.Split(':'));
Or, use AddRange method and do this
ListBox1.Items.AddRange(File.ReadLines(filepath)
.SelectMany(line=>line.Split(':')
.Cast<object>() // I think this is redundant remove if not required.
.ToArray()
);
I am trying to get some Sitecore items and then sort them by their creation date with newest items first.
I have the following code (snippet):
itemID = Constants.BucketIds.NEWS;
Item pressItem = context.GetItem(itemID);
var pressChildItems = context
.SelectItems("/sitecore/content" + pressItem.Paths.ContentPath + "/*")
.OrderByDescending(x => x.Fields[Sitecore.FieldIDs.Created]);
foreach (Item childItem in pressChildItems)
{
// DO SOMETHING
}
I am getting the following error back:
At least one object must implement IComparable.
I am not sure how I am supposed to fix this.
Do not order by Field, sort by its value. Remove .Fields from your line:
var pressChildItems = context
.SelectItems("/sitecore/content" + pressItem.Paths.ContentPath + "/*")
.OrderByDescending(x => x[Sitecore.FieldIDs.Created]);
Dates are stored as yyyyMMddHHmmss... strings, so sorting by value as string will give you exactly the same effect as getting date value from field and ordering using the date.
Since it looks like you have your items in a Bucket, you should really use the ContentSearch API (and limit the results if you are using them on the front-end since a bucket could potentially contain thousands of items).
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.Linq;
using Sitecore.ContentSearch.SearchTypes;
using Sitecore.Data.Items;
List<Item> ResultsItems = new List<Item>();
SitecoreIndexableItem bucket = Context.Database.GetItem(Constants.BucketIds.NEWS);
using (var searchcontext = ContentSearchManager.GetIndex(bucket).CreateSearchContext())
{
IQueryable<SearchResultItem> searchQuery =
searchcontext.GetQueryable<SearchResultItem>()
.OrderByDescending(x => x.CreatedDate)
.Take(10);
SearchResults<SearchResultItem> results = searchQuery.GetResults();
// fetch the Sitecore Items if you do not want to work with the SearchResultItem
foreach (var hit in results.Hits)
{
Item item = hit.Document.GetItem();
if (item != null)
{
ResultsItems.Add(item);
}
}
}
I'd like to loop over a string list, and find out if the items from this list start with one of the item from another list.
So I have something like:
List<string> firstList = new List<string>();
firstList.Add("txt random");
firstList.Add("text ok");
List<string> keyWords = new List<string>();
keyWords.Add("txt");
keyWords.Add("Text");
You can do that using a couple simple for each loops.
foreach (var t in firstList) {
foreach (var u in keyWords) {
if (t.StartsWith(u) {
// Do something here.
}
}
}
If you just want a list and you'd rather not use query expressions (I don't like them myself; they just don't look like real code to me)
var matches = firstList.Where(fl => keyWords.Any(kw => fl.StartsWith(kw)));
from item in firstList
from word in keyWords
where item.StartsWith(word)
select item
Try this one it is working fine.
var result = firstList.Where(x => keyWords.Any(y => x.StartsWith(y)));
I have a list in which I filter, according to the text input in a TextBox in Xaml. The code below filters the List stored in the results variable. The code checks if the textbox input,ie, queryString, matches the Name of any item in the results list EXACTLY. This only brings back the items from the list where the string matches the Name of a the item exactly.
var filteredItems = results.Where(
p => string.Equals(p.Name, queryString, StringComparison.OrdinalIgnoreCase));
How do I change this so that it returns the items in the list whose Name, is similar to the queryString?
To describe what I mean by Similar:
An item in the list has a Name= Smirnoff Vodka. I want it so that if "vodka" or "smirnoff" is entered in the textbox, the the item Smirnoff Vodka will be returned.
As it is with the code above, to get Smirnoff Vodka returned as a result, the exact Name "Smirnoff Vodka" would have to be entered in the textbox.
It really depends on what you mean, by saying "similar"
Options:
1) var filteredItems = results.Where( p => p.Name != null && p.Name.ToUpper().Contains(queryString.ToUpper());
2) There is also also known algorithm as "Levenshtein distance":
http://en.wikipedia.org/wiki/Levenshtein_distance
http://www.codeproject.com/Articles/13525/Fast-memory-efficient-Levenshtein-algorithm
The last link contains the source code in c#. By using it you cann determine "how close" the query string to the string in your list.
Try this:
fileList.Where(item => filterList.Contains(item))
Try this:
var query = "Smirnoff Vodka";
var queryList = query.Split(new [] {" "}, StringSplitOptions.RemoveEmptyEntries);
var fileList = new List<string>{"smirnoff soup", "absolut vodka", "beer"};
var result = from file in fileList
from item in queryList
where file.ToLower().Contains(item.ToLower())
select file;