A simple linq query to start the day - linq

I have a class that contains a ints, string and pointers to other classes. I'm trying to extract the strings and perform a substring operation on them before I select.Distinct. My LINQ code looks right
List<string> crops = (from m in cropTypes
let cw = m.CropName
let kw = cw.Substring(0, cw.LastIndexOf(")") + 1)
select(kw).Distinct()).ToList();
I have also tried
var crop = …
List<string> crops = crop.ToList();
When I attempt to compile, I'm getting
Cannot implicitly convert type
System.Collections.Generic.List<System.Collections.Generic.IEnumerable<char>> to System.Collections.Generic.List<System.Collections.Generic.IEnumerable<string>>
on the ToList() line.
m.CropName is definitely a string
Why does the compiler think that I'm using a char list rather than a string list and how do I fix this.
Nothing like a simple problem to stump you at the start of a day!

try
List<string> crops = (from m in cropTypes
let cw = m.CropName
let kw = cw.Substring(0, cw.LastIndexOf(")") + 1)
select kw).Distinct().ToList();
If you call Distinct on a string, you're actually enumerating the string's characters.

Related

Office Script - Split strings in vector & use dynamic cell address - Run an excel script from Power Automate

I'm completely new on Office Script (with only old experience on Python and C++) and I'm trying to run a rather "simple" Office Script on excel from power automate. The goal is to fill specific cells (always the same, their position shouldn't change) on the excel file.
The power Automate part is working, the problem is managing to use the information sent to Excel, in excel.
The script take three variables from Power automate (all three strings) and should fill specific cells based on these. CMQ_Name: string to use as is.
Version: string to use as is.
PT_Name: String with names separated by a ";". The goal is to split it in as much string as needed (I'm stocking them in an Array) and write each name in cells on top of each other, always starting on the same position (cell A2).
I'm able to use CMQ_Names & Version and put them in the cell they're supposed to go in, I've already make it works.
However, I cannot make the last part (in bold above, part 2 in the code below) work.
Learning on this has been pretty frustrating as some elements seems to sometime works and sometimes not. Newbie me is probably having syntax issues more than anyting...  
function main(workbook: ExcelScript.Workbook,
CMQ_Name: string,
Version: string,
PT_Name: string )
{
// create reference for each sheet in the excel document
let NAMES = workbook.getWorksheet("CMQ_NAMES");
let TERMS = workbook.getWorksheet("CMQ_TERMS");
//------Part 1: Update entries in sheet CMQ_NAMES
NAMES.getRange("A2").setValues(CMQ_Name);
NAMES.getRange("D2").setValues(Version);
//Update entries in sheet CMQ_TERMS
TERMS.getRange("A2").setValues(CMQ_Name);
//-------Part 2: work with PT_Name
//Split PT_Name
let ARRAY1: string[] = PT_Name.split(";");
let CELL: string;
let B: string = "B"
for (var i = 0; i < ARRAY1.length; i++) {
CELL = B.concat(i.toString());
NAMES.getRange(CELL).setValues(ARRAY1[i]);
}
}
  I have several problems:
Some parts (basically anything with red are detected as a problem and I have no idea why. Some research indicated it could be false positive, other not. It's not the biggest problem either as it seems the code sometimes works despite these warnings.
Argument of type 'string' is not assignable to parameter of type '(string | number | boolean)[ ][ ]'.
I couldn't find a way to use a variable as address to select a specific cell to write in, which is preventing the for loop at the end from working.  I've been bashing my head against this for a week now without solving it.
Could you kindly take a look?
Thank you!!
I tried several workarounds and other syntaxes without much success. Writing the first two strings in cells work, working with the third string doesn't.
EDIT: Thanks to the below comment, I managed to make it work:
function main(
workbook: ExcelScript.Workbook,
CMQ_Name: string,
Version: string,
PT_Name: string )
{
// create reference for each table
let NAMES = workbook.getWorksheet("CMQ_NAMES");
let TERMS = workbook.getWorksheet("CMQ_TERMS");
//------Part 0: clear previous info
TERMS.getRange("B2:B200").clear()
//------Part 1: Update entries in sheet CMQ_NAMES
NAMES.getRange("A2").setValue(CMQ_Name);
NAMES.getRange("D2").setValue(Version);
//Update entries in sheet CMQ_TERMS
TERMS.getRange("A2").setValue(CMQ_Name);
//-------Part 2: work with PT_Name
//Split PT_Name
let ARRAY1: string[] = PT_Name.split(";");
let CELL: string;
let B: string = "B"
for (var i = 2; i < ARRAY1.length + 2; i++) {
CELL = B.concat(i.toString());
//console.log(CELL); //debugging
TERMS.getRange(CELL).setValue(ARRAY1[i - 2]);
}
}
You're using setValues() (plural) which accepts a 2 dimensional array of values that contains the data for the given rows and columns.
You need to look at using setValue() instead as that takes a single argument of type any.
https://learn.microsoft.com/en-us/javascript/api/office-scripts/excelscript/excelscript.range?view=office-scripts#excelscript-excelscript-range-setvalue-member(1)
As for using a variable to retrieve a single cell (or set of cells for that matter), you really just need to use the getRange() method to do that, this is a basic example ...
function main(workbook: ExcelScript.Workbook) {
let cellAddress: string = "A4";
let range: ExcelScript.Range = workbook.getWorksheet("Data").getRange(cellAddress);
console.log(range.getAddress());
}
If you want to specify multiple ranges, just change cellAddress to something like this ... A4:C10
That method also accepts named ranges.

If Statement error: Expressions that yield variant data-type cannot be used to define calculated columns

I'm new in Power BI and I'm more used to work with Excel. I try to translate following Excel formula:
=IF(A2="UPL";0;IF(MID(D2;FIND("OTP";D2)+3;1)=" ";"1";(MID(D2;FIND("OTP";D2)+3;1))))
in Power Bi as follows:
Algo =
VAR FindIT = FIND("OTP",Fixed_onTop_Data[Delivery Date],1,0)
RETURN
IF(Fixed_onTop_Data[Delivery Type] = "UPL", 0,
IF(FindIT = BLANK(), 1, MID(Fixed_onTop_Data[Delivery Date],FindIT+3,1))
)
Unfortunately I receive following error message:
Expressions that yield variant data-type cannot be used to define calculated columns.
My values are as follows:
Thank you so much for your help!
You cant mix Two datatypes in your output; In one part of if, you return an INT (literally 0/1), and is second you return a STRING
MID(Fixed_onTop_Data[Delivery Date],FindIT+3,1)
You must unify your output datatype -> everything to string or everything to INT
Your code must be returning BLANK in some cells therefore PowerBI isn't able to choose a data type for the column, wrap your code inside CONVERT(,INTEGER).

Use Array<String> in a Flux

Could you guys help me out with using Array and stream (?) over it to use single element (String) to save Movie to db and return FLux. Spring specific stuff isn't important - just the way to iterate over alphabet and create random Movies. What's the best and most-kotlinish way of doing this?
val alphabet = arrayOf("A".."Z")
val exampleMovies: Flux<Movie> = Flux.just(alphabet)
.flatMap { movieRepository.save(Movie(name = it)) }
I'm getting compilation error:
Error:(15, 62) Kotlin: Type mismatch: inferred type is Array<ClosedRange<String>>! but String? was expected
The problem is that arrayOf("A".."Z") will give an Array<ClosedRange<String>>, i.e. the array has one element of type ClosedRange. What you actually wanted to have is an Array<String> with elements A, B, C, ..., Z I guess? Unfortunately, the range operator doesn't work like this for Strings, explained here.
Instead, create that array by mapping a CharRange accordingly:
val alphabet = ('A'..'Z').map(Char::toString).toTypedArray()

How to use Linq Aggregate Query to print line sequence number alongwith some data from the List<string>?

I have a simple List like
List<string> Test=new List<string>() {"A","B","C"}
I am using a simple Linq.Aggregate as under to get a string from the elements of this List as under:-
string Output= Test.Aggregate((First, Next) => First + "\r\n" + Next);
This gives me the result like(new line separated):
A
B
C
However,i want result with a sequence number on each line,ie like this:-
1)A
2)B
3)C
How do i do this using linq?
Select has an overload that will give you the index of the element to work with so you could do Select((x,i)=>String.Format("{0}){1}", i+1,x)). Or in full:
string output= Test.Select((x,i)=>String.Format("{0}){1}", i+1,x)).Aggregate((First, Next) => First + "\r\n" + Next);
One thing worth mentioning though is that string concatenation in a loop (and in the Aggregate counts as in a loop) is generally considered a bad idea for performance reasons. You should consider using alternative methods such as a StringBuilder:
string output = Test
.Aggregate (new StringBuilder(), (sb, x) => sb.AppendFormat("{0}){1}\r\n", lineCount++, x))
.ToString();
I wouldn't use Aggregate here, just a Select to get the index and join the resulting list back together to make a single string, for example:
var output = string.Join("\r\n",
Test.Select((s, index) => $"{index+1}){s}"));

sequence operators not supported for type 'system.string'

what is the problem in this query
var ptypes = (from mf in _pagecontext.PagesRefs
let a = mf.nvcr_Slug.Substring(mf.nvcr_Slug.LastIndexOf("/") + 1) // gets everything after /
let b = Regex.Replace(a, #"[\d-]+$", m => m.Value.Replace('-', '=')) // replace last char with =
let cc = (b.Contains('=') ? b.Substring(0, b.IndexOf("=")) : b) // strip off everything before = to get original string
let cm = stroriginal // string to search
where cm.Equals(cc)
select mf);
nvcr_slug could be
mazhar-kaunain-baig-3-4
mazhar-kaunain-baig-3-4/mazhar-kaunain-baig-3-4
mazhar-kaunain-baig-3-4/mazhar-kaunain-baig-3-4/mazhar-kaunain-baig
abc
abc/abc
abc/abc/abc
UPDATE:
Based on your comment - I think this should work:
let b = Regex.Replace(a, #".$", '=')
In each iteration over the collection with LINQ you are dealing with just one value - the above should capture the last character in the given string and replace it with =
The first thing that I can think of is a conflict between LINQ and System.String implementations of the method Contains on:
b.Contains('=')
Try using System.String.Contains explicitly.
Use
let cc = (b.Contains("=") ? b.Substring(0, b.IndexOf("=")) : b)
and try.

Resources