I need a fast way to create immutable Lists in one line just like Java's List.of(), but in C#. What's the equivalent to this syntax?
List<String> strings = List.of("first", "second");
You could use ImmutableList.Create
ImmutableList<string> list = ImmutableList.Create("first", "second");
You could also use AsReadOnly which returns a wrapper for the list:
ReadOnlyCollection<string> readonlyList = new List<string> { "first", "second" }.AsReadOnly();
However, as this is just a wrappper you can always modify the underlying list, so it's not truly immutable.
Try this code:
var strings = new List<string> { "first", "second" };
Related
I have a list of strings (thing1-3, else1-3, other1-3), and I want to create a simplified list with just (thing, else, other). Seems straight forward (or at least this was with the Classic VB Dictionary .Exists function), but I'm stuck. So I'm checking if the string startswith one of my simplified strings, then if the simplified list does not contain that string, add it. But checking if the simplified list contains the string already is throwing me off.
List<string> myList = new List<string>(new string[] { "thing1", "thing2", "thing3", "else1", "else2", "else3", "other1", "other2", "other3" });
List<string> myListSimplified = new List<string>();
foreach (string s in myList)
{
if (s.StartsWith("thing"))
{
if (!myListSimplifed.Contains("thing")) { myListSimplifed.Add("thing"); }
}
if (s.StartsWith("else"))
{
if (!myListSimplifed.Contains("else")) { myListSimplifed.Add("else"); }
}
if (s.StartsWith("other"))
{
if (!myListSimplifed.Contains("other")) { myListSimplifed.Add("other"); }
}
}
I would expect this mySimplifiedList to contain "thing", "else", "other", but it contains thing1-3, else1-2, other1-3.
if (myListSimplified.Exists("thing")) { }
IntelliSense returns "cannot convert from 'string' to 'System.Predicate'
ok.. so this:
if (!myListSimplified.Any(str => str.Contains("thing"))) { myListSimplified.Add("thing"); }
Or
if (!myListSimplified.Exists(str => str.Contains("thing"))) { myListSimplified.Add("thing"); }
None of these work.
Obviously I can create a method to iterate through the list and compare it to a string, but this functionality seems to be too fundamental to lists that MS left it out... Also seems silly to be passing lists around...
private bool Exists(List<string> lList, string sCompare)
{
bool bVal = false;
foreach (string s in lList)
{
if (s == sCompare) { bVal = true; }
break;
}
return bVal;
}
I'm not sure what your problem is:
First of all, it seems your first code snippet contains a typo: you have List<string> myListSimplified but then inside the foreach you reference myListSimplifed (missing 'i' after the 'f').
If I correct that typo and run your code, then I get a list containing {"thing", "else", "other" }, which seems to be what you also expect.
Besides the typo in myListSimplifed vs myListSimplified your code sample produces what you want it to do.
Not what you ask for, but you can have the same effect with far fewer lines of code:
var myList = new List<string> {"thing1", "thing2", "thing3", "else1", "else2", "else3", "other1", "other2", "other3"};
var myListSimplified = myList.Select(s => new string(s.Where(char.IsLetter).ToArray())).Distinct();
Lists are generic data types. They don't know what strings are, and so they're not provided out of the box with facilities to search for items that StartWith or Contain other strings. This sort of operation doesn't make sense, generically speaking. This is why you have operations like Any that take a lambda function to provide your own logic:
if (myList.Any(str => str.StartsWith("thing")))
mySimplifiedList.Add("thing");
I've tested this and it works fine.
Of course, if you have multiple strings you want to extract, you should probably make this more generic. The simplest way is to extract the lines above to a method that receives the substring ("thing", in this case) as a parameter. A more generic approach (assuming it matches your data and logic) would be to go over all strings, strip all numerals from it, and store that. Assuming StripNumerals is a method that receives a string, it could look like this, with Distinct ensuring you have only one instance of each string.
var simplifiedList = myList.Select(StripNumerals).Distinct().ToList();
I have noticed your typo when putting the code in Visual Studio. The result is correct, but your algorithm is far from being generic. What you can try:
var is useful to simplify declaration
list initialization can be simplified
obtain a list by stripping all digits and perform a distinct on it
var myList = new List<string>() { "thing1", "thing2", "thing3", "else1", "else2", "else3", "other1", "other2", "other3" };
var listWithoutNumbers = myList.Select(s =>
{
Regex rgx = new Regex("[0-9]");
return rgx.Replace(s, "");
});
var simplifiedList = listWithoutNumbers.Distinct();
Your original solution works, apart from the typo.
However, if you want more generic solution, you could use something like this
List<string> myList = new List<string>(new string[] { "thing1", "thing2", "thing3", "else1", "else2", "else3", "other1", "other2", "other3" });
List<string> myListSimplified = myList.Select(s => new String(s.Where(Char.IsLetter).ToArray())).Distinct().ToList();
Don't forget to add
using System.Linq;
if you will try this solution.
I tried searching by "C# new string array pass dynamic" but could not find anything relevant.
int[] IDs = someMethodCall();
List<string> values = new List<string>();
foreach (int i in IDs)
{
values.Add(i.ToString());
}
someClass sc = new someClass();
sc.Value = new string[] { "values.string1", "values.string2", ... };
What I'm trying to do is to pass the strings from values to sc.Value, so I don't have to write them out (since I don't what they'll be beforehand).
sc.Value is a string[] as defined by the class I'm using from an API (not written by me).
What is the best way to do this dynamically? In other words, how to pass in dynamic values to a string[] construction?
If I'm not missing something,you can just use ToArray method
sc.Value = values.ToArray();
BTW, you don't even need to create a list in the first place:
sc.Value = someMethodCall().Select(x => x.ToString()).ToArray();
I'm a little confused by the way you word your questioning, but I think you are trying to send your list to an array, which is easily done using the code below:
List<string> values = new List<string>();
sc.Value = values.ToArray();
How about just using the built-in method ToArray:
sc.Value = values.ToArray();
Comes with List, and is an extension method for IEnumerable if you can use LINQ.
I have two string arrays
string[] a = ...
string[] b = ...
I want to remove any items from a that also exist in b or return a new array with only those items that exist only in a.
So, for example, if
a={"a", "b", "c"};
and,
b={"b"}
then the result should be
{"a", "c"}
Is there a neat lambda expression or Linq or something I can use to do this?
Thanks,
Sachin
I believe Except will do what you want. Remember, Except, like most LINQ Extension methods, will not modify the existing collection. It will return a new collection.
c = a.Except(b)
How is it possible to initialize (with a C# initializer) a list of strings? I have tried with the example below but it's not working.
List<string> optionList = new List<string>
{
"AdditionalCardPersonAddressType","AutomaticRaiseCreditLimit","CardDeliveryTimeWeekDay"
}();
Just remove () at the end.
List<string> optionList = new List<string>
{ "AdditionalCardPersonAdressType", /* rest of elements */ };
List<string> mylist = new List<string>(new string[] { "element1", "element2", "element3" });
You haven't really asked a question, but the code should be
List<string> optionList = new List<string> { "string1", "string2", ..., "stringN"};
i.e. no trailing () after the list.
var animals = new List<string> { "bird", "dog" };
List<string> animals= new List<string> { "bird", "dog" };
Above two are the shortest ways, please see https://www.dotnetperls.com/list
Your function is just fine but isn't working because you put the () after the last }. If you move the () to the top just next to new List<string>() the error stops.
Sample below:
List<string> optionList = new List<string>()
{
"AdditionalCardPersonAdressType","AutomaticRaiseCreditLimit","CardDeliveryTimeWeekDay"
};
If you are using C# 9.0 and up you can use the new feature target-typed new expressions Link
Example:
List<string> stringList = new(){"item1","item2", "item3"} ;
The right way to initialize along with declaration is :
List<string> optionList = new List<string>()
{
"AdditionalCardPersonAdressType","AutomaticRaiseCreditLimit","CardDeliveryTimeWeekDay"
};
This is how you initialize and also you can use List.Add() in case you want to make it more dynamic.
List<string> optionList = new List<string> {"AdditionalCardPersonAdressType"};
optionList.Add("AutomaticRaiseCreditLimit");
optionList.Add("CardDeliveryTimeWeekDay");
In this way, if you are taking values in from IO, you can add it to a dynamically allocated list.
Move round brackets like this:
var optionList = new List<string>(){"AdditionalCardPersonAdressType","AutomaticRaiseCreditLimit","CardDeliveryTimeWeekDay"};
One really cool feature is that list initializer works just fine with custom classes too: you have just to implement the IEnumerable interface and have a method called Add.
So for example if you have a custom class like this:
class MyCustomCollection : System.Collections.IEnumerable
{
List<string> _items = new List<string>();
public void Add(string item)
{
_items.Add(item);
}
public IEnumerator GetEnumerator()
{
return _items.GetEnumerator();
}
}
this will work:
var myTestCollection = new MyCustomCollection()
{
"item1",
"item2"
}
There is something else that you might be missing that hasn't been mentioned. I think it might be the problem you are having as I suspect you already tried removing the trailing () and still got an error.
First, like others have mentioned here, in your example you do need to remove the trailing ();
But, also, note that List<> is in the System.Collections.Generic namespace.
So, you need to do one of the following two options:
[#1 below is probably the more preferred option]
(1)
Include the use of the namespace at the top of your code with:
using System.Collections.Generic;
or
(2)
Put the fully qualified path to List in your declaration.
System.Collections.Generic.List optList=new System.Collections.Generic.List
{ "AdditionalCardPersonAddressType","AutomaticRaiseCreditLimit","CardDeliveryTimeWeekDay"
};
Hope that helps.
The error message you receive when you implement List correctly but don't include the System.Collections.Generic namespace is misleading and not helpful:
"Compiler Error CS0308: The non-generic type List cannot be used with type arguments."
PS - It gives this unhelpful error because if you don't specify that you intend to use System.Collections.Generic.List the compiler assumes you are trying to use System.Windows.Documents.List.
I have seen the content tag C#, but if someone could use Java (the same search terms lead here):
List<String> mylist = Arrays.asList(new String[] {"element1", "element2", "element3" }.clone());
This is how you would do it.
List <string> list1 = new List <string>();
Do Not Forget to add
using System.Collections.Generic;
In Java, i like to use constructs such as
List<String> list = new ArrayList<String>() {{add("foo");}};
Is there a way to do this in 1 line in C#, too?
This is called a collection initializer and it's part of C# 3.0.
As well as lists, you can initialize collections of more complicated types, so long as they implement IEnumerable and have approprate Add methods for each element in the collection initializer. For example, you can use the Add(key, value) method of Dictionary<TKey, TValue> like this:
var dict = new Dictionary<string, int>
{
{"first", 10 },
{"second", 20 }
};
More details can be found in chapter 8 of C# in Depth, which can be downloaded free from Manning's web site.
I think what you want is an array initializer
List<string> list = new List<string>() { "foo" };
Multiple items should be comma-separated
List<string> list = new List<string>() { "foo","bar","bas"};
You can do it in .NET 3.5 to set property values:
List<string> list = new List<string> () { Property = Value, Property2 = Value2 };
Or to initialize an array:
List<string> list = new List<string> () { "value1", "value2" };
You can't call methods this way, however.
If you just need to deal with adding objects to a collection, then collection initializers work great, but if you need more static initialization to be performed, you can use something called a static constructor that works the same as a static initializer in java
This has poor formatting but seems to cover it