Custom sort logic in OrderBy using LINQ - c#

What would be the right way to sort a list of strings where I want items starting with an underscore '_', to be at the bottom of the list, otherwise everything is alphabetical.
Right now I'm doing something like this,
autoList.OrderBy(a => a.StartsWith("_") ? "ZZZZZZ"+a : a )

If you want custom ordering, but don't want to supply a comparer, you can have it - sql style:
autoList
.OrderBy(a => a.StartsWith("_") ? 2 : 1 )
.ThenBy(a => a);

I think you need to use OrderBy(Func<>, IComparer<>) and specify your own Comparer which will implement your custom logic .

Use the overload of OrderBy that takes an IComparer, the first Func argument will feed the comparer, and from there you need to compare the strings. First deal with the case of one or both starts with _, and then from there you will probably need to strip the _ and just use the standard string.Compare to sort them beyond the first _

Related

Different treatment for single multiline parameter

I want to enforce the first parameter to be placed on a new line if there are several parameters and not all of them are placed on a single line
this is the setting for that: csharp_wrap_after_invocation_lpar = true
now in a case when there is a single parameter but it spans multiple lines e.g. a ternary expression or a lambda, I prefer it to start on the same line
.Select(r => r.Id == Id.None
? new Unload()
: new Load(r.Id));
instead of
.Select(
r => r.Id == Id.None
? new Unload()
: new Load(r.Id));
is there a way to achieve this?
I played around and was not able to find a setting for your desired behavior. Therefore I'd say it's not possible. But of course, you can ask JetBrains support.

Sitecore ContentSearch LIKE operator fails on non-alpha characters

I am attempting to implement a custom search in Sitecore 7.5 using the ContentSearch.LINQ library and making use of fuzzy search. For strings containing only alpha characters and whitespace, it works like a charm, i.e. "cxlcium" will return results for "calcium." However, the end goal of this is more to protect against common misspellings - "St Johns Wort" should return items with "St. John's Wort." Interestingly enough, "St. Johns Wort" will return zero results, and an exact match will throw an exception due to the single quote (I'm assuming that may need to be escaped, though it works without issue on StartsWith or Contains type searches). I have tried moving the minimumSimilarity value up and down to no avail.
For what it's worth, this is also passing through to a Coveo index rather than Lucene.
Thanks in advance for any insight.
Code is as follows:
var productResults = context.GetQueryable<SearchResultItem>()
.Where(x => x["productname"].Like(searchQuery, .7f)
.Take(10)
.OrderBy(x => x["productname"])
.GetResults();
You might be better off using the phonetic match extension provided by Coveo. More info here:
https://developers.coveo.com/display/public/SC201409/Coveo+LINQ+Extensions

How to convert a search string to a boolean condition?

I have a search criteria stored in a string:
string Searchstr = "(r.Value.Contains("PwC") || (r.Value.Contains("Canadian") && r.Value.Contains("thrive"))) || (r.Value.Contains("Banana") && r.Value.Contains("Gayle"))"
I want to use this in a If statement to check the values:
if(searchstr)
{
then do this....
}
but the if should have a searchstr as boolean.
How to convert this to boolean?
EDIT: The requirement is to give search criteria dynamically in a text box in the following format - "PwC OR (Canadian AND thrive)".
Which will be used to search an XML file.
Therefore I have loaded an XML file and want to have a Where condition in LINQ for which I need to use Dynamic LINQ but string is not allowed in that and also I have some braces to deal with.
Thinking of that I have taken the resultset from the XML(The tag value which i need to search)
var selectedBook = from r in document.Root.Descendants("Archives").Elements("Headline").Elements("Para")
select r;
and would ideally like to try something like:
var query=selectedbook.Where(searchstr)
OR
if(searchstr){....then do this}
You will need to do a bit of work to make this happen, but it is possible.
You should have a look at the dynamic LINQ library. This allows you to specify LINQ conditions (and other clauses) as strings and execute them just like LINQ operators.
Start with the explanation on ScottGu's blog and follow the links:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
I'm assuming the string is going to reference only a specific set of objects (r or r.Value in this case, for example - or anything else you want, as long as you know it beforehand). If this is the case, then:
Create a delegate that takes the objects (that may be referenced) as parameters
and returns a bool, as you want.
Programmatically write a small C# source file in memory that defines the query
as the body of a method (with a fixed name, preferably) that conforms to the delegate specified above.
Use the CSharpCodeProvider class to compile an assembly
with your custom function that returns the bool you want.
Run the dynamically written and compiled code from your main program.
Well as you may guess it is not going to be straight forward but at the same time it is not as hard a problem as it seems
You can perform a few steps to get what you want:
Get the search expression as input (for e.g. "PwC OR (Canadian AND thrive)")
Write an extension method on XElement that returns true and takes the search criteria as input. You will then be able to use
var selectedBook = from r in
document.Root.Descendants("Archives").Elements("Headline").Elements("Para")
where r.SatisfiesCriteria(searchCriteria)
select r;
Write a parser class that parses searchCritera and stores it in parsed format. (for e.g. you can convert it into postfix notation). This is quite easy and you can use standard algorithm for this. For your purpose OR, AND will be operators and PwC etc. will be operands. Parenthesis will get removed as part of parsing.
Now simply invoke this parser from with in your extension method and then evaluate the postfix expression you get. This again can be done through standard stack based evaluation. Infact it would be better if you parse the criteria once and then only evaluate in where. While evaluating you need to replace the operands with r.Value.Contains
It seems like a good scenario for http://scriptcs.net/

Check if dictionary contains substring?

Say I have two dictionaries with the following key value pairs:
1, "Hello"
2, "Example"
And another dictionary as follows:
1, "HelloWorld"
2, "Example2"
I want to find out if these dictionaries contain the substring "hello" within them. dictionary.ContainsValue("Hello") will work for the first example but not the second one. How can I check for existence of a substring in all values in a dictionary?
Just use Any to to check for the first Value that contains "Hello"
dictionary.Any(kvp=>kvp.Value.Contains("Hello"))
Dictionary doesn't allow to search for substrings. To find it, you need to enumerate all values and check each for substring, as suggested by juharr. However, this method is highly inefficient. Use it only if you don't care about search performance at all.
If you need good performance, use suffix array algorithm. https://en.wikipedia.org/wiki/Suffix_array
dictionary.Values.Any(v => v.Contains("Hello"));
Dictionary isn't an IEnumerable itself so it won't have LINQ extensions apply to it.

Default String Sort Order

Is the default sort order an implementation detail? or how is it that the Default Comparer is selected?
It reminds me of the advice. "Don't store HashCodes in the database"
Is the following Code guaranteed to sort the string in the same order?
string[] randomStrings = { "Hello", "There", "World", "The", "Secrete", "To", "Life", };
randomStrings.ToList().Sort();
Strings are always sorted in alphabetical order.
The default (string.CompareTo()) uses the Unicode comparison rules of the current culture:
public int CompareTo(String strB) {
if (strB==null) {
return 1;
}
return CultureInfo.CurrentCulture.CompareInfo.Compare(this, strB, 0);
}
This overload of List<T>.Sort uses the default comparer for strings, which is implemented like this:
This method performs a word (case-sensitive and culture-sensitive)
comparison using the current culture. For more information about word,
string, and ordinal sorts, see System.Globalization.CompareOptions.
If you do not specify a comparer then sort will use the default comparer which sorts alphabetically. So to answer your question yes that code will always return the strings in the same order.
There is an overload to the sort method that allows you to specify your own comparer if you wish to sort the data in a different order.
I wanted to post a reply related to cultural things while you sort your strings but Jon already added it:-(. Yes, I think you may take into acc the issue too because it is selected by default the alphabetical order, the random strings if existed as foreign besides English (i.e Spanish) will be placed after English after all, they appear in the same first letters though. That means you need a globalization namespace to deal with it.
By the way, Timothy, it is secret not secrete :D
Your code creates a new list copying from the array, sorts that list, and then discards it. It does not change the array at all.
try:
Array.Sort(randomStrings);

Categories