Dynamic linQ on string array - arrays

I have a string array like this.
string[] ColumnArray = new string[] { First story, second data , third way };
Following is the linQ query on this array.
string query = (from x in ColumnArray
where x.Contains("Story")
select x).First();
But sometimes the query will be like this.
string query = (from x in ColumnArray
where ( x.Contains("Story") || x.Contains("View"))
select x).First();
That condition should add dynamically. SO how the dynamic LinQ can helps here.
I have written something like this.
string dynamiccondition= // some condition.
var query = (from x in ColumnArray.AsEnumerable().AsQueryable().Where(dynamiccondition).Select(x));
// but this is not working.
Any suggestion?

In DynamicLINQ you can use logical operation like AND(&&) and OR(||), so try something like this
string dynamiccondition="it.Contains(\"Story\") OR it.Contains(\"View\")"
var query = ColumnArray.AsQueryable()
.Where(dynamiccondition);

Related

Kotlin - Find matching objects in array

Let's say I have an array of strings and I want to get a list with objects that match, such as:
var locales=Locale.getAvailableLocales()
val filtered = locales.filter { l-> l.language=="en" }
except, instead of a single value I want to compare it with another list, like:
val lang = listOf("en", "fr", "es")
How do I do that? I'm looking for a one-liner solution without any loops. Thanks!
Like this
var locales = Locale.getAvailableLocales()
val filtered = locales.filter { l -> lang.contains(l.language)}
As pointed out in comments, you can skip naming the parameter to the lambda, and use it keyword to have either of the following:
val filtered1 = locales.filter{ lang.contains(it.language) }
val filtered2 = locales.filter{ it.language in lang }
Just remember to have a suitable data structure for the languages, so that the contains() method has low time complexity like a Set.

appendRow from an array

If I have an array, [Joe, John, Adam, Sam, Bill, Bob] and I want to try to add this to a new row by doing SpreadsheetApp.getActive().getSheetByName('Sheet4').appendRow([array]); , what happens is that the entire list of names goes into 1 cell. Is there a way to break this up so they file away into the same row, but different columns? I need to continue using appendRow however.
I get this:
But I really want to have it look like this:
var my2DArrayFromRng = datasheet.getRange("A:A").getValues();
var a = my2DArrayFromRng.join().split(',').filter(Boolean);
var array = [];
for (d in a) {
array.push(a[d]);
}
SpreadsheetApp.getActive().getSheetByName('Sheet4').appendRow([array.toString()]);
You are converting your array to a string before you post it which is causing your issue.
Do not use the array.toString() method inside append row. Instead just append the array as it is.
SpreadsheetApp.getActive().getSheetByName('Sheet4').appendRow(array);

Passing a full-text search parameter using Dapper.net

Consider this simple query which use full text searching on the Keywords field:
DECLARE #searchTerm VARCHAR(500) = 'painted'
SELECT * FROM StockCatalogueItems
WHERE (CONTAINS(KeyWords, #searchTerm))
This works as expected, but I need to do the same using a Dapper.net parameterised query. When using stored procedures, I create the full text parameter like this: "\"painted*\""
But using the same approach this doesn't work using dapper. No results are returned. This is the line in the query where I use the parameter:
AND (CONTAINS(KeyWords, #search))
and it's passed to the query like so:
return _context.Database.Connection.Query<StockProfileMatrix>(basequery, new
{
search = searchTerm
}
I can only assume that dapper is sanitising the string somehow, removing quotes perhaps?
Any ideas?
This works for me. However the tech stack am working on is .net core RTM and "Dapper": "1.50.0-rc3",
_dbConnection.QueryAsync<Guid>(#"select br.Id from Brand br where CONTAINS(br.Text,#Name)",new {Name = $"\"*{name}*\""}))
For completeness, I'll answer the question. The query syntax is correct, but the way in which the full-text parameter is created was obviously not. I created an extension method that formats the parameter:
public static string ToFullText(this string str)
{
string searchTerm = null;
if (!string.IsNullOrEmpty(str))
{
string[] keywords = str.Trim().Split(null);
foreach (var keyword in keywords)
{
searchTerm += string.Format("\"{0}*\" AND ", keyword);
}
if (searchTerm != null)
searchTerm = searchTerm.Substring(0, searchTerm.LastIndexOf(" AND "));
}
return searchTerm;
}
Then I call the method when I pass the parameter in to the dapper query:
_context.Database.Connection.Query<dynamic>(query, new
{
search = filter.SearchTerm.ToFullText()
});

Using LINQ to find Excel columns that don't exist in array?

I have a solution that works for what I want, but I'm hoping to get some slick LINQ types to help me improve what I have, and learn something new in the process.
The code below is used verify that certain column names exist on a spreadsheet. I was torn between using column index values or column names to find them. They both have good and bad points, but decided to go with column names. They'll always exist, and sometimes in different order, though I'm working on this.
Details:
GetData() method returns a DataTable from the Excel spreadsheet. I cycle through all the required field names from my array, looking to see if it matches with something in the column collection on the spreadsheet. If not, then I append the missing column name to an output parameter from the method. I need both the boolean value and the missing fields variable, and I wasn't sure of a better way than using the output parameter. I then remove the last comma from the appended string for the display on the UI. If the StringBuilder object isn't null (I could have used the missingFieldCounter too) then I know there's at least one missing field, bool will be false. Otherwise, I just return output param as empty, and method as true.
So, Is there a more slick, all-in-one way to check if fields are missing, and somehow report on them?
private bool ValidateFile(out string errorFields)
{
data = GetData();
List<string> requiredNames = new [] { "Site AB#", "Site#", "Site Name", "Address", "City", "St", "Zip" }.ToList();
StringBuilder missingFields = null;
var missingFieldCounter = 0;
foreach (var name in requiredNames)
{
var foundColumn = from DataColumn c in data.Columns
where c.ColumnName == name
select c;
if (!foundColumn.Any())
{
if (missingFields == null)
missingFields = new StringBuilder();
missingFieldCounter++;
missingFields.Append(name + ",");
}
}
if (missingFields != null)
{
errorFields = missingFields.ToString().Substring(0, (missingFields.ToString().Length - 1));
return false;
}
errorFields = string.Empty;
return true;
}
Here is the linq solution that makes the same.
I call the ToArray() function to activate the linq statement
(from col in requiredNames.Except(
from dataCol in data
select dataCol.ColumnName
)
select missingFields.Append(col + ", ")
).ToArray();
errorFields = missingFields.ToString();
Console.WriteLine(errorFields);

Custom query with Castle ActiveRecord

I'm trying to figure out how to execute a custom query with Castle ActiveRecord.
I was able to run simple query that returns my entity, but what I really need is the query like that below (with custom field set):
select count(1) as cnt, data from workstationevent where serverdatetime >= :minDate and serverdatetime < :maxDate and userId = 1 group by data having count(1) > :threshold
Thanks!
In this case what you want is HqlBasedQuery. Your query will be a projection, so what you'll get back will be an ArrayList of tuples containing the results (the content of each element of the ArrayList will depend on the query, but for more than one value will be object[]).
HqlBasedQuery query = new HqlBasedQuery(typeof(WorkStationEvent),
"select count(1) as cnt, data from workstationevent where
serverdatetime >= :minDate and serverdatetime < :maxDate
and userId = 1 group by data having count(1) > :threshold");
var results =
(ArrayList)ActiveRecordMediator.ExecuteQuery(query);
foreach(object[] tuple in results)
{
int count = (int)tuple[0]; // = cnt
string data = (string)tuple[1]; // = data (assuming this is a string)
// do something here with these results
}
You can create an anonymous type to hold the results in a more meaningful fashion. For example:
var results = from summary in
(ArrayList)ActiveRecordMediator.ExecuteQuery(query)
select new {
Count = (int)summary[0], Data = (string)summary[1]
};
Now results will contain a collection of anonymous types with properties Count and Data. Or indeed you could create your own summary type and populate it out this way too.
ActiveRecord also has the ProjectionQuery which does much the same thing but can only return actual mapped properties rather than aggregates or functions as you can with HQL.
Be aware though, if you're using ActiveRecord 1.0.3 (RC3) as I was, this will result in a runtime InvalidCastException. ActiveRecordMediator.ExecuteQuery returns an ArrayList and not a generic ICollection. So in order to make it work, just change this line:
var results = (ICollection<object[]>) ActiveRecordMediator.ExecuteQuery(query);
to
var results = (ArrayList) ActiveRecordMediator.ExecuteQuery(query);
and it should work.
Also note that using count(1) in your hql statement will make the query return an ArrayList of String instead of an ArrayList of object[] (which is what you get when using count(*).)
Just thought I'd point this out for the sake of having it all documented in one place.

Resources