I would like to sort an array in JavaScript as asc. After I used sort method, the result is like below.
[ '123, '12', '1A1', '1A', '1a', 'A1', 'A2', 'AB', 'A', 'Ab', 'a1', 'a2', 'aB', 'ab' ]
When I'm using sort Array.Sort() by C#, the result is like below.
{ "12", "123", "1a", "1A", "1A1", "A", "a1", "A1", "a2", "A2", "ab", "aB", "Ab", "AB" }
Actually the C# sort way is what I want, so how to implement it in JavaScript? Has anyone completed this task before? A comparator function is really appreciate.
Array.prototype.sort uses string comparison by default. It seems you want to compare case insensitive - you could pass in a comparator function that uses toLowerCase (but beware of the difference with .toLocaleLowerCase!):
a.sort(function(a, b) {
a = a.toLowerCase(); b = b.toLowerCase();
return a > b ? 1 : a < b ? -1 : 0;
});
Related
I'm using ASP.NET Core 2.1. I have settings in appsettings.json and I bind them to classes using the options pattern. I want to override some of them in appsettings.Production.json.
Overriding is supported according to the docs, and works for me generally.
But it doesn't work for arrays.
appsettings.json:
"MySectionOuter": {
"MySectionInner": [
{
"foo": "1",
"bar": "2",
"baz": "3"
},
{
"foo": "a",
"bar": "b",
"baz": "c"
}
]
}
My overrides in appsettings.Production.json
"MySectionOuter": {
"MySectionInner": [
{
"bar": "4",
},
{
"baz": "d"
}
]
}
However that doesn't work - it adds rather than replaces.
I read that the array is syntactic sugar for a key-value store. So I also tried this:
"MySectionOuter": {
"MySection:1": {
"bar": "4",
},
"MySection:2": {
"baz": "b",
}
}
But that also doesn't work.
What is the correct syntax?
UPDATE
The comments show I haven't explained properly. What I want is like this:
During development:
element1: foo=1
element1: bar=2
element1: baz=3
element2: foo=a
element2: bar=b
element2: baz=c
During production:
element1: foo=1
element1: bar=2
element1: baz=4 // this was changed
element2: foo=a
element2: bar=b
element2: baz=d // this was changed
In fact, there are no arrays there when the configuration is built. It's just a key-value pair dictionary. So you end up with string keys, something like
"mysectionouter:mysectioninner:0:foo" = 1.
So when in your config you define an array, the following happens:
appsettings.json:
"mysectionouter:mysectioninner:0:foo" = 1
"mysectionouter:mysectioninner:0:bar" = 2
appsettings.production.json:
"mysectionouter:mysectioninner:0:bar" = new1
result:
foo = 1
bar = new1
So it's just index-based, and next configuration just overrides a key. In your second example, you achieve nothing but changing the index. Representation would be:
"mysectionouter:mysectioninner:1:bar" = new1
So back to your question: arrays are tricky in appsettings, and though supported, are generally hard and not intuitive to use.
By index you may get a weird merge of two not related objects, if you define different sets of settings in your files, like settings A and B in the first config, and C in second, you will get C and B in the result, and you likely don't want to have B at all. Worse still, you can get a mix of A and C if you define only some fields of each object.
I'd recommend using some other files for storing this kind of information. You can also break in the debugger just where the configuration is loaded and see for yourself how these keys are build to get more insight.
According to this blog post: https://www.paraesthesia.com/archive/2018/06/20/microsoft-extensions-configuration-deep-dive/
It's not possible to remove configuration items with a provider.
You can add configuration at override time, but you can’t remove things. The best you can do is override a value with an empty string.
Instead you should only fill as little information as needed in the appsettings.config and fill the appropriate settings in a more specialized settings file. E.g. appsettings.Development.config or your appsettings.Production.config. Or as suggested in the blog post:
Since you can’t remove things, specify as little configuration as possible and behave correctly using defaults in your code when configuration isn’t there.
I was actually having a similar issue in dotnet 6, when trying to merge arrays from multiple appsettings, when I stumbled across this thread.
The solution was actually way simpler then thought.
Microsoft.Extensions.Configuration merges arrays through the index:
{ foo: [1, 2, 3] } + { foo: [4, 5] } = { foo: 4, 5, 3 }
But we want to be able to declare which entries override others and which ones should be added to the list. And we do this by declaring a GUID as dictionary key instead of an array.
{
"foo": {
"870622cb-0372-49f3-a46e-07a1bd0db769": 1,
"cbb3af55-94ea-41a5-bbb5-cb936ac47249": 2,
"9410fcdc-28b3-4bff-bfed-4d7286b33294": 3
}
}
+
{
"foo": {
"cbb3af55-94ea-41a5-bbb5-cb936ac47249": 4,
"1c43fa78-b8db-41f8-809d-759a4bc35ee2": 5,
}
}
=
{
"foo": {
"870622cb-0372-49f3-a46e-07a1bd0db769": 1,
"cbb3af55-94ea-41a5-bbb5-cb936ac47249": 4, /*2 changed to 4 because key equals*/
"9410fcdc-28b3-4bff-bfed-4d7286b33294": 3
"1c43fa78-b8db-41f8-809d-759a4bc35ee2": 5, /*while 5 added to the list*/
}
}
This may seem inconventient at first, because one would think, that
((IConfiguration)config).GetSection("foo").Get<int[]>();
Throws some kind of invalid type exception, since a Guid is not what we know as array index.
But it can actually (implicitly!) return the merged "foo" section above as int[].
Last year I asked how to traverse and print jagged arrays, without having to write an overloaded function for each dimension that gets added. Generic printing of jagged arrays.
I picked up the problem again and was able to solve it like this. It is similar to one of the answers I got, but not quite the same.
static string Print<T>(T[] array)
{
string str = "[ ";
for (int i = 0; i < array.Length; i++)
{
str += array[i];
if (i < array.Length - 1)
str += ", ";
}
return str + " ]\n";
}
static string Print<T>(T[][] array)
{
string str = "";
for (int i = 0; i < array.Length; i++)
{
var sub = array[i];
if (sub.Length != 0 && sub[0] is Array)
str += PrintDynamic(sub);
else
str += Print(sub);
}
return str + "\n";
}
private static string PrintDynamic(dynamic array)
{
return Print(array);
}
It works fine and I get the correct output:
var twoDim = new int[][]
{
new int[] { 0, 1, 2, 3 },
new int[] { 0, 1, 2 },
new int[] { 0 }
};
var threeDim = new int[][][] { twoDim, twoDim }
Console.WriteLine(Print(threeDim));
// Output:
// [ 0, 1, 2, 3]
// [ 0, 1, 2]
// [ 0 ]
//
// [ 0, 1, 2, 3]
// [ 0, 1, 2]
// [ 0 ]
But I'm still not satisfied, because it would be a lot nicer if I didnt't need PrintDynamic() and if I could just write
str += Print(sub);
instead of
str += PrintDynamic(sub);
That's where my question comes from. If I change that one line, I do not get any errors, but the output becomes
// [ System.Int32[], System.Int32[], System.Int32[], System.Int32[]]
// [ System.Int32[], System.Int32[], System.Int32[]]
// [ System.Int32[] ]
//
// [ System.Int32[], System.Int32[], System.Int32[], System.Int32[]]
// [ System.Int32[], System.Int32[], System.Int32[]]
// [ System.Int32[] ]
because Print<T>(T[] array) gets called instead of Print<T>(T[][] array). How does the compiler know which Print<T>() to use, when it's called from PrintDynamic(dynamic array), but doesn't when it's called from within Print<T>()?
To answer your original question. When you call:
str += Print(sub)
and the original object for the method was int[][][], then the <T> for the method is int[]. So you are calling Print(sub) with T[], where T is int[].
Therefore, the T[] overload of Print is selected, with T as int[] - and everything follows as expected. This is compile time resolved, and is the best the compiler can do with the information it has.
Remember, a generic method is only compiled to IL once - you don't get 'different versions' for different ways it happens to be called (unlike with C++ templates). The generic method's behaviour must be valid for all possible inputs. So if the method receives T[][], and you extract sub-elements internally, it can only consider the sub-object type to be T[]. It can't detect at runtime that 'oh, actually, T is an int[], so I'll call a different overload'. The method will only ever call the T[] overload of Print(sub), no matter what the input.
However, in the case where you use dynamic, you're ignoring all the generic type information baked in at compile time, and saying 'what is this type actually NOW, at runtime, using reflection. Which method is the best match now? Use that one!'. This behaviour has a significant overhead, and therefore must be explicitly requested by using the dynamic keyword.
"How does the compiler know which Print() to use, when it's called from PrintDynamic(dynamic array)"
The answer is virtual function tables. Since you are working with C#, all types inherit from the class "object". A simple call to Print() attempts to print the objects themselves and not their content. Why? Because the ToString() method is called for the object since a more appropriate method has not been overloaded. Whenever you're working with strongly typed OOP languages such as C#, each object is a pointer to it's data structure (generally on the heap), and the first entry of this data structure is a pointer to the virtual function table for that object. A virtual function table is essentially an array of function pointers for each respective function that the class supports. Since by calling PrintDynamic you are actually passing the pointer of your object, the resolution of your object's pointer maps back to the virtual function table of its class. Then, the appropriate overloaded functions can be called. This is a high level description of the process. The concept is similar in languages such as C++. I hope this helps you understand a bit more about what the compiler is actually doing behind the scenes. I'd recommend some academic reading or perhaps the following link for some more details.
https://en.wikipedia.org/wiki/Virtual_method_table
If I were you, as this is a problem that can't really be resolved at compile time for arbitrary dimensions, I'd avoid using generics altogether:
public static string Print(Array array)
{
string str = "[ ";
for (int i = 0; i < array.Length; i++)
{
var element = array.GetValue(i);
if (element is Array)
str += Print(element as Array);
else
{
str += element;
if (i < array.Length - 1)
str += ", ";
}
}
return str + " ]";
}
This produces nested output, which I think is nicer, and it will nest arbitrarily as the depth increases.
[ [ [ 0, 1, 2, 3 ][ 0, 1, 2 ][ 0 ] ][ [ 0, 1, 2, 3 ][ 0, 1, 2 ][ 0 ] ] ]
This question already has answers here:
How to Sort a List<T> by a property in the object
(23 answers)
Closed 7 years ago.
I have a list
List<string[]> listname = ...
The list looks like this:
[string][string][string]
I want to sort the list by second string.
The second string is a number presented as a string, i want to keep it that way, i need it like this.
I want the numbers to be in Increasing order.
Example for data:
["RDP"]["3389"]["TCP"]
["HTTP"]["80"]["TCP"]
["HTTPS"]["443"]["TCP"]
I want to sort by the post number.
In this example "RDP" will become the last one.
How can I do so?
var sortedList = listname.OrderBy(l => int.Parse(l[1]));
This assumes that the second entry in each array is parsable as int. If you're not sure about that, you'd need to add some checks and maybe use int.TryParse.
You can refer to appropriate index of an array in OrderBy:
var l = new List<string[]>() {
new string[] { "a", "b", "c" },
new string[] { "b", "a", "c" },
new string[] { "c", "c", "c" },
};
var s = l.OrderBy(c => c[1]).ToList();
Having the code below, why is the variable declaration considered as correct syntax, but not also the method call?
public static void Func(string[] p)
{
}
public static void Test()
{
string[] a = { "x", "y", "z" };
Func({"x", "y", "z"});
}
It looks like everybody else is focusing on the workaround (which is simply to specify that you need a new [] { "some", "strings" }. The why is a little less obvious though.
The former is valid because the compiler knows to use your initialization syntax to create an Array (because you've defined it as such).
The later would have some issues. It may seem trivial in this case because the compiler should, theoretically, be able to figure out that you need a string[]. Think about cases where you have a Func<IEnumerable<string>> though. What type gets generated in that case? Would the compiler take a wild-ass guess? Always use an Array (even though there might be a better fit)? It could be one of a number of possibilities.
I'm guessing that's the reason that the language specification doesn't allow for passing things this way.
You need to pass in a value as the argument. {"x", "y", "z"} is not a value. It can be used as short-hand for initializing a variable.
Note that both of these are valid:
List<string> a = new List<string>() {"x", "y", "z"};
string[] b = new string[] {"x", "y", "z"};
And the full version of what it represents:
List<string> a = new List<string>();
a.Add("x");
a.Add("y");
a.Add("z");
So you need to make an object (new)
new [] {"x", "y", "z"}
Or make an object beforehand and pass that in.
As for why this is like this, you need to pass in a value, not a helper for array initialization.
You can initialize the object directly on the inside of the method call, but do not think a good practice.
where you used:
Func ({"x", "y", "z"});
The above form you tried to pass an object not instantiated, ie it does not already exist on your "context". The correct is you initialize it to be generated in a reference memory to this value and thus the "Func" method you can use it.
In the case of variable declaration:
string[] a = {"x", "y", "z"};
In this case your compiler is reading:
string[] a = new string[] {"x", "y", "z"};
It does this interpretation alone, without requiring you to do object initialization explicitly.
So my answer is best for this situation you must first create the object then pass it as a parameter to the method:
string[] a = {"x", "y", "z"};
Func (s);
Is there any possibility to decode Morse code to text if the code is in following format(without any white spaces):
-.-..--.....-...--..----.
Normally it looks like that,
- .-. .- -. ... .-.. .- - .. --- -.
t r a n s l a t i o n
but is it possible, to get the same text from Morse code without white spaces?
This is possible to do, but it becomes problematic as you end up generating a large number of possible options.
First start with a Morse mapping:
private Dictionary<string, string> map = new Dictionary<string, string>()
{
{ ".-", "a" },
{ "-...", "b" },
{ "-.-.", "c" },
{ "-..", "d" },
{ ".", "e" },
{ "..-.", "f" },
{ "--.", "g" },
{ "....", "h" },
{ "..", "i" },
{ ".---", "j" },
{ "-.-", "k" },
{ ".-..", "l" },
{ "--", "m" },
{ "-.", "n" },
{ "---", "o" },
{ ".--.", "p" },
{ "--.-", "q" },
{ ".-.", "r" },
{ "...", "s" },
{ "-", "t" },
{ "..-", "u" },
{ "...-", "v" },
{ ".--", "x" },
{ "-..-", "y" },
{ "-.--", "z" },
{ "--..", " " },
};
Then this function can produce the possible decodings:
public IEnumerable<string> DecodeMorse(string morse)
{
var letters =
map
.Where(kvp => morse.StartsWith(kvp.Key))
.Select(kvp => new
{
letter = kvp.Value,
remainder = morse.Substring(kvp.Key.Length)
})
.ToArray();
if (letters.Any())
{
var query =
from l in letters
from x in DecodeMorse(l.remainder)
select l.letter + x;
return query.ToArray();
}
else
{
return new [] { "" };
}
}
Now, given a shorter version of your input morse, "-.-..--....", I got 741 possible strings. Here's the cut down version:
cabe
cadee
cadi
…
tranie
trans
trateeee
…
trxii
trxse
It includes "trans" so it seems to be working.
Running on the full string produces 5,914,901 possible with "translation" as one of the possibilities.
Incidentally, there were 4,519 possible strings that simply started with "trans". How humans could do this on the fly is amazing!
What you are proposing isn't really possible.
You will not be able to tell where one letter ends and the next begins. How will you be able to tell the difference between letters? Will the first letter be -, -., or -.-?
There is no doubt in my mind that given a sufficiently advanced algorithm, and sufficient context around each letter, that it is possible to get a high level of accuracy. However the problem approaches AGI-level difficulty the greater accuracy that you require, because this is one of the skills (fast pattern matching in language) that humans are particularly good at and machines are nowhere near as good at (yet). The reason for that, is that broader context that makes pattern matching possible for humans includes not just possible words, but semantics and the overall meaning of the story, and mapping that to model of the world that makes sense. This is something that is extremely difficult to program a computer to do. Also the human brain is massively parallel.
Also, it is fairly trivial to prove that a general perfect solution is impossible (perfect accurate translation for every possible input string). For example, consider simply the short string ".--", that could mean "at" or "em", both valid English words.
You need to know where the characters start and end. Take, for instance:
...---...
If you divide it one way, you get:
... --- ... = SOS
However, if you divide it differently, you may get:
. .. - -- . .. = EITMEI
So, is it possible? Technically, yes, it's possible. However, you would have a huge number of possible solutions that would take a long time to identify and translate. With a database of commonly seen words, you might be able to make this a bit smarter, but it would still be a best-effort.