Get the first element of System.array? - c#

I am writing a script for a task in DisplayFusion. There's an array with window classes of which I need the first.
How to get the first element of System.array regardless of the index' type?
I tried
String windowClass = BFS.Window.GetClass(myArray[Array.IndexOf(myArray)]);
but that throws an error
(No overloading for method 'IndexOf', accepts 1-Arguments)

IndexOf is for finding the index of the first element in the array that matches the value you passed. I think you're after [0].
String windowClass = BFS.Window.GetClass(myArray[0]);
Please note that if the array is empty this will throw an exception.
You could also use .First() or FirstOrDefault() from System.Linq, but [0] is made for what you need.

Related

Linq - Is Exact String in String Array

I'm trying to write a Linq query that loops through a set of Umbraco nodes and checks if it's Document Type Alias is in a string array. I've got something very close:
if (allowedDocTypes != null && allowedDocTypes.Length > 0)
{
allowedDocTypes = allowedDocTypes.Where(x => !string.IsNullOrEmpty(x)).ToArray();
nodes = nodes.Where(x => x.DocumentTypeAlias.ContainsAny(allowedDocTypes));
}
allowedDocTypes is a string array that includes the document types. The first line inside the if statement removes any empty strings from the array. Finally, I'm making use of the ContainsAny method to check if the document type alias is in the string array.
This almost works in that it'll check if the document type alias contains any of the string in the string array. However, it works for partial matches as well but I really need exact matches.
For example, the string array has a value of review in it. What ContainsAny appears to do is pull through all the nodes with a document type alias of review but it'll also pull through any with a document type alias of preview.
Is there a way to easily change this so that review would be an exact match rather than partial?
Thanks,
Ben
All you really should have to do is reverse the logic a bit and use Contains:
nodes = nodes.Where(x => allowedDocTypes.Contains(x.DocumentTypeAlias));

Please explain what's going on in this part of the C# code using line => line and .toArray

Here's the code:
File.ReadLines(sourceFilePath).Select(line => line.Split('\t')).ToArray();
I get what's going on up until the "Select" keyword. Can someone please break down what is going on in "line => line.Split...
My understanding is that we are going line by line through the text file and parsing and splitting a line of input text by tabs (since I know the text is tab-delimited). But, what exactly is going on with "line => line..."?
And I get at the end of the line of code the text is going into an Array. But when I debug and step through the code and use the locals window what is the name of the Array that contains what has been read? How do I see what is read into the Array?
This is saying, essentially, "For each line in the file, split the line on the tab character into an array of strings, then create an array of those arrays (such that each element in the returned array is an array)"
The Select function takes an Enumerable of something and applies a function to each item, producing 1 output value for each input value. In other programming languages this is called a Map or a Projection.
The => indicates a lambda expression which is compiled into a delegate function. It takes an argument called "line", whose type is inferred by the usage (because ReadLines returns an IEnumerable of Strings, line is of type String).
The lambda's body has an implied return type of the value resulting from the last call (the call to Split). Thus, the line says "run this lambda on each line".
Finally, the call to .ToArray at the end (outside of the lambda) converts the IEnumerable<String[]> returned by Select into an array of arrays (String[][]).
The => is a lambda expression - think of it as a type of delegate or as an Function. Each item that is returned from File.Readlines is operated on by the Select - the Select passes each line through the lambda function line => line.Split('\t') which takes a single argument (named line) and then returns the result of calling .Split('\t') on the line argument.
The Select operator is a LINQ extension method used to handle projecting elements from a collection into a different form. The most common usage would be to select a single column from the elements of that collection into a new collection, however more complex projections can be handled inside the lambda expression.
The compiler automatically infers the datatype returned by the Select method so that its dependent on whatever the output is of the lambda you pass in. In your case, the output of the lambda is an Array of strings, so ultimately it returns an IEnumerable<string[]>. When you call ToArray() at the end, you then convert the IEnumerable<string[]> into a concrete string[][].
This is Linq.
The Select method is an extension on IEnumerable, it lets you 'project' each result into some other form using a lambda expression (the line => ... part)
In this case, the developer wants to split each line on the tab character (resulting in an array, this is the projection) and retrieve an array containing each result.

Inserting a string into a list<string> element?

I'm using this line of code to insert a value from an array into a certain line, in a list of lines.
lineList[LineNumber].Insert(lineList[LineNumber].Count(), pArray[i]);
After debugging all the variables are correct, the pArray is passed in as a parameter and lineList is inherited from another class. I can't see why this wouldnt work, all the lines that are added are just empty?
This is because .NET strings are immutable; string.Insert returns a new string, rather than modifying an existing one. If you need to modify the string, add an assignment, like this:
lineList[LineNumber] = lineList[LineNumber]
.Insert(lineList[LineNumber].Count(), pArray[i]);
This should be equivalent to
lineList[LineNumber] += pArray[i];

Need some help with a XElement Query

This query isn't working as I'm expecting it to. Anyone see the problem?
I'm trying to get an element by it's name, but it's not returning anything. Here is the specific part of the function I need some help with:
Update
The solution was to use an XName instead of a string. Like so:
var matchingElements = elements.Where(e => e.Name.Equals(XName.Get(name)));
Try changing your line to:
elements.Where(e => e.Name.LocalName == name)
The LocalName part is the important part, as otherwise you are comparing equality of an XName with a string. Remember, XML supports names of the style "prefix:element-name". In that example, "prefix" is the identifier associated with the namespace returned by e.Name.Namespace and "element-name" is the identifier returned by e.Name.LocalName.
Kirk's answer is right on the money. I wanted to point out a few issues with your code.
This line unnecessarily counts all the elements:
var hasMatch = matchingElements.Count() > 0;
You can replace it with Any() which will terminate early once an element is found:
var hasMatch = matchingElements.Any();
Next, having verified that hasMatch is true you should call First() instead of FirstOrDefault() since you know it has to have a value at that point.
Having said that, you could actually rewrite your code as follows:
var matchingElement = elements.FirstOrDefault(e => e.Name.LocalName == name);
return (string)matchingElement;
Here casting to a string will return the value of the element if it was found, otherwise it would return null. The cast is used just in case it was null since you wouldn't be able to use matchingElement.Value which would throw a NullReferenceException if no element was found. You should also consider using SingleOrDefault if you expect only one element to exist.
I think you need to add the root namespace to the name of the element.
You can also try using the XContainer.Descendants(XName) method instead.

problem getting xpath function ends-with() to work while contains() works fine

i am trying to get the tags that have an attribute that end with a certain id.
like <span id="ctl00_ContentPlaceHolder1_Country">
i want to get the spans that have the id ends with 'Country'
i try the following xpath //span[ends-with(#id,'Country')] but i get the following exception
"Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function."
the strange thing is that contains works fine
so the following xpath works //span[contains(#id,'Country')]
any ideas why this happens?
thanks
The function ends-with() is not defined for XPath 1.0 but only for XPath 2.0 and XQuery.
You are using .NET. .NET at this date does not implement XPath 2.0, XSLT 2.0 or XQuery.
One can easily construct an XPath 1.0 expression, the evaluation of which produces the same result as the function ends-with():
$str2 = substring($str1, string-length($str1)- string-length($str2) +1)
produces the same boolean result (true() or false()) as:
ends-with($str1, $str2)
In your concrete case you just need to substitute the right expressions for $str1 and $str2. They are, accordingly, /myXml/data and 'World'.
So, the XPath 1.0 expression to use, that is equivalent to the XPath 2.0 expression ends-with(/myXml/data, 'World') is:
'World' =
substring(/myXml/data,
string-length(/myXml/data) - string-length('World') +1
)
contains() and starts-with() are in XSLT1; ends-with() is in XSLT2 only.
Date: Jan 6th 2016
For any one reading this answer, these are the Xpath String functions supported in latest .Net 4.6 framework:
concat: Returns the concatenation of the arguments.
contains: Returns true if the first argument string contains the second argument string; otherwise returns false.
normalize-space: Returns the argument string with the white space stripped.
starts-with: Returns true if the first argument string starts with the second argument string; otherwise returns false.
string: Converts an object to a string.
string-length: Returns the number of characters in the string.
substring: Returns the substring of the first argument starting at the position specified in the second argument and the length specified in the third argument.
substring-after: Returns the substring of the first argument string that follows the first occurrence of the second argument string in the first argument string.
substring-before: Returns the substring of the first argument string that precedes the first occurrence of the second argument string in the first argument string.
translate: Returns the first argument string with occurrences of characters in the second argument string replaced by the character at the corresponding position in the third argument string.
MSDN Source

Categories