I have an array of strings that I am looping through. I would like to loop through the array and on each iteration, create a new object with a name that matches the string value.
For example;
string[] array = new string[] { "one", "two", "three" };
class myClass(){
public myClass(){
}
}
foreach (string name in array)
{
myClass *value of name here* = new myClass();
}
Would result in three objects being instantiated, with the names "one", "two" and "three".
Is this possible or is there are better solution?
What are you trying to do is not possible in statically-typed language. IIRC, that's possible on PHP, and it's not advisable though.
Use dictionary instead: http://ideone.com/vChWD
using System;
using System.Collections.Generic;
class myClass{
public string Name { get; set; }
public myClass(){
}
}
class MainClass
{
public static void Main()
{
string[] array = new string[] { "one", "two", "three" };
IDictionary<string,myClass> col= new Dictionary<string,myClass>();
foreach (string name in array)
{
col[name] = new myClass { Name = "hahah " + name + "!"};
}
foreach(var x in col.Values)
{
Console.WriteLine(x.Name);
}
Console.WriteLine("Test");
Console.WriteLine(col["two"].Name);
}
}
Output:
hahah one!
hahah two!
hahah three!
Test
hahah two!
While others have given you an alternate but no one is telling why do they recommend you that.
That's because You cannot access object with dynamic names.
(Food for thought: Just think for a moment if you could do so, how will you access them before they are even coded/named.)
Instead create a Dictionary<string, myClass> as others mentioned.
Use a Dictionary<String, myClass> instead:
var dict= new Dictionary<String, myClass>();
foreach (string name in array)
{
dict.Add(name, new myClass());
}
Now you can access the myClass instances by your names:
var one = dict["one"];
or in a loop:
foreach (string name in array)
{
myClass m = dict[ name ];
}
You can use this approach:
var array = [srt1, srt2, str3];
var other_array = [];
for(var i = 0; i < array.length; i++){
other_array.push({
name: array[i]
})
}
And for lookup it is easy to find the instance you need by filtering:
var instance1 = other_array.filter(function(result) {
return result.name == 'str1';
});
Looks like you need a list of dictionary of your objects:
var myClassDictionary = new Dictionary<string,myClass>();
foreach (string name in array)
{
myClassDicationry.Add(name, new myClass());
}
// usage:
// myClass["one"] <- an instance of myClass
There are no programming languages that I know of that let you define variable names in runtime.
You could do something like this -
Dictionary<string, myClass> classes = new Dictionary<string, myClass>();
foreach(string name in array)
{
classes[name] = new myClass();
}
Then you can refer to the named instances later
classes[name].MyClassMethod();
You can use the following code.
string[] array = new string[] { "one", "two", "three" };
Dictionary<String, myClass> list;
class myClass(){
public myClass(){
list = new Dictionary<String, myClass>();
}
}
foreach (string name in array)
{
list.Add(name, new myClass())
}
You can use lists to store the objects so you can access them
list<myClass> myClasses = new List<myClass>();
foreach (myClass object in myClasses)
{
//preform interaction with your classes here
}
Not applicable to C#, or any statically-typed language for that matter.
For curiosity, I tried if what I remembered in PHP(creating variables on-the-fly) is still correct.
It's still the same PHP, last I used it was year 2000. You can generate variables on-the-fly, not saying it's advisable though, it pollutes the global variables, it can corrupt some existing variable or object with same name.
https://ideone.com/nJDiou
<?php
class MyClass
{
private $v;
function __construct($x) {
$this->v = $x;
}
public function getValue() {
return $this->v;
}
}
$one = new MyClass("I'm tough!");
echo "The one: " . $one->getValue() . "\n";
$i = 0;
foreach(array("one","two","three") as $h) {
$$h = new MyClass("Says who? " . ++$i);
}
echo "The one: " . $one->getValue() . "\n";
echo $two->getValue() . "\n";
echo $three->getValue() . "\n";
echo "loop\n";
foreach(array("three","one","two") as $h) {
echo $$h->getValue() . "\n";
}
?>
Outputs:
The one: I'm tough!
The one: Says who? 1
Says who? 2
Says who? 3
loop
Says who? 3
Says who? 1
Says who? 2
Related
I have a ListBox where table names are written like this:
Staging_Section_01_2019_03_19_01
Staging_Section_01_2019_03_20_01
Staging_Section_23_2019_03_21_01
Staging_Section_52_2019_03_23_01
Staging_Section_52_2019_03_24_01
What I am trying to do is to separate them by Section Number, so I want all Section_01 in one List object and Section_23 in another List object, so on and so forth. The dynamic nature is whats making it difficult for me.
So far, I have the following:
foreach (var it in uploadBox.Items)
{
if (it.ToString().Contains("Section"))
{
section = it.ToString().Substring(0, 18);
found = it.ToString().IndexOf("_");
section = section.Substring(found + 1);
sectionNum = section.Substring(8, 2);
}
}
I have gotten the sectionNum which would just be the number and section, which is the string like Section_01.
Any idea on how to approach this?
The expected output would be something like this:
List 1
Staging_Section_01_2019_03_19_01
Staging_Section_01_2019_03_20_01
List 2
Staging_Section_23_2019_03_21_01
List 3
Staging_Section_52_2019_03_23_01
Staging_Section_52_2019_03_24_01
I would use a Dictionary<string, List<string>> for this. Each 'section' that is parsed would be a key, and the remaining portion would the the value.
Dictionary<string, List<string>> myDict = new Dictionary<string, List<string>>();
foreach (var it in uploadBox.Items)
{
if (it.ToString().Contains("Section"))
{
section = it.ToString().Substring(0, 18);
found = it.ToString().IndexOf("_");
section = section.Substring(found + 1);
sectionNum = section.Substring(8, 2);
if(!myDict.ContainsKey(sectionNum))
{
myDict.Add(sectionNum, new List<string> { someOtherValue });
}
else
{
myDict[sectionNum].Add(someOtherValue);
}
}
}
Unless I have completely misinterpreted your question, I think this is a potential solution to your dynamic objects.
you could do something like this:
var sections = new Dictionary<string, List<string>>();
foreach(var it in uploadBox.Items)
{
var item = it.ToString();
if(item.Contains("Section"))
{
var section = GetSection(item);
if(!sections.ContainsKey(section))
{
sections.Add(section, new List<string>());
}
sections[section].Add(item);
}
}
private string GetSection(string item)
{
var split = item.Split("_");
return $"{split[1]}_{split[2]}";
}
It is best to regex for this kind of task:
uploadBox.Items
.GroupBy(x => Regex.Match(x.ToString(), #"^\w+_Section_(?<section>\d+)").Groups["section"].Value)
I have a string "hello", and a integer 1.
I want to convert them into
new { hello= 1 }
dynamically, and without using any condition like
switch(p1){
case "hello":
return new {hello=p2};
}
as there is many different string and I need to put many items into a super object set like
var emotion = {smile=1,angry=2,worry=3}
the problem is smile, angry and worry was string. but after added to emotion, they are not string, but just an index (like dictionary, however dictionary's index also has dataType, which is not my expected result)
Is it possible?
--- Updated --- i have added a function to specify the expected output.
private void Question_1()
{
//i have
string a = "hello";
int b = 1;
// i want to convert a and b to new {a = b} programmatically, for example i can convert a and b to a Tuple like
Tuple<string, int> x = new Tuple<string, int>(a,b);
//but i dont know how to to convert it to new {a = b}, as i need to put the string "hello" as key to new {a=b}
var result = new { hello = b }; //you can see i can put b after =, but i can never put the string hello at the left
}
private void Question_2()
{
//and the final should be like this
List<Tuple<string, int>> list = new List<Tuple<string, int>>() {
new Tuple<string,int>("smile",1),
new Tuple<string,int>("cry",2),
new Tuple<string,int>("worry",3)
};
foreach (Tuple<string, int> item in list)
{
//adding item's string and int into result and finally the result is
}
//the final result
var finalResult = new { smile = 1, cry = 2, worry = 3 };
}
Use .NET naming conventions for enums: They should be Pascal Notation.
enum Emotion
{
Smile = 1, Angry = 2, Worry = 3
}
var l = new List<Emotion> { Emotion.Angry, Emotion.Smile, Emotion.Worry };
You can also use a friendly name for your enum with the DesriptionAttribute like this:
enum Emotion
{
[Description("Smiling")]
Smile = 1,
[Description("Angry Type")]
Angry = 2,
[Description("Worry Type")]
Worry = 3
}
Any reason you can't just use a dictionary?
var hi = new Dictionary<string,int>();
hi[p1] = p2;
return hi; // Would serialize the same way as your anonymous object
If not, then you could use the expando object to dynamically set properties at runtime.
var hi = new ExpandoObject() as IDictionary<string, object>;
hi.Add(p1, p2);
var p2Value = (int)((dynamic)hi).hello;
You can use ExpandoObject.
class Program
{
static dynamic obj = new ExpandoObject();
static void Main(string[] args)
{
AddProperty("City", "Sydney");
AddProperty("Country", "Australia");
AddProperty("hello", 1);
Console.WriteLine(obj.City);
Console.WriteLine(obj.Country);
Console.WriteLine(obj.hello);
//We can even use dynamic property names ( e.g. cityProp in below example )
IDictionary<string, object> dic = obj as IDictionary<string, object>;
Console.WriteLine("City is : " + dic[cityProp]);
}
public static void AddProperty(string propertyName, object value)
{
IDictionary<string, object> a = obj as IDictionary<string, object>;
a[propertyName] = value;
}
}
dynamic emotion = new { smile = 1, angry = 2, worry = 3 };
Console.WriteLine(emotion.smile);
Like this?
Edit: Based on your comment on another answer:
it is not worked, i need it able to be accepted by
Url.Action("action","controller", x), where x is thing that i'm trying
to create dynamically . i don't know if dynamic too complex or what.
but Url.Action dont know how to read it
There's obviously more to the question than just C#, clearly this an MVC question. You should really add as much information as you can about what you need.
Your answer is probably here:
https://stackoverflow.com/a/15112223/1685167
The #Url.Action() method is proccess on the server side, so you cannot
pass a client side value to this function as a parameter.
Edit
The approach taken here was completely wrong. This is how it should have been done.
public class Recipe {
public List<string> ingredients;
public string result;
public Recipe (List<string> _ingredients, string _result) {
this.ingredients _ingredients;
this.result = _result;
}
}
And then when looping:
Recipe[] recipes = new Recipe[] {
new Recipe(new List<string>(new string[] { "potato", "tabasco" }), "explosivePotato"),
new Recipe(new List<string>(new string[] { "mentos", "cola" }), "colaCannon"),
new Recipe(new List<string>(new string[] { "potato", "cola" }), "potatoCola"),
new Recipe(new List<string>(new string[] { "potato", "chips" }), "potatoChips")
}
This would also mean that looping would be a whole lot simpler.
Original question
I have a C# script with the following array:
string[,] craftingRecipes = new string[,]{
// {recipe},{result}
{"potato","tabasco"},{"explosivePotato"},
{"mentos","cola"},{"colaCannon"},
{"potato","cola"},{"potatoCola"},
{"potato","chips"},{"potatoChips"}
};
How can i loop through every item in the n'th subarray? So for example the array containing {"potato","tabasco"} should be looped twice, since there are two items in it.
Thank you for any help!
I'm not sure I understood your question, since your code doesn't compile, but you can use this loop to iterate through items in first "line":
int line = 0;
for (int i = 0; i < craftingRecipes.GetLength(1); i++)
{
Console.WriteLine(craftingRecipes[line,i]);
}
Although, Your array should look more like this (I had to add sth_missing_here, because Multi-Dimensional Array must have sub-arrays with the same length):
string[,] craftingRecipes = new string[,]{
{"potato","tabasco"},{"explosivePotato","sth_missing_here_1"},
{"mentos","cola"},{"colaCannon","sth_missing_here_2"},
{"potato","cola"},{"potatoCola","sth_missing_here_3"},
{"potato","chips"},{"potatoChips","sth_missing_here_3"}
};
You can use the OfType<T> method, to convert the multidimensional array into an IEnumerable<T> result, for sample:
IEnumerable<string> items = craftingRecipes.OfType<int>();
foreach(var item in items)
{
// loop between all elements...
}
As per the edit 19-09-2018, this can now be properly answered.
Iterate over the array using two simple nested foreach loops.
foreach (Recipe recipe in recipes) {
System.Console.Write("To make '{0}' you need:", recipe.result);
foreach (ingredient in recipe.ingredients) {
System.Console.Write(ingredient);
}
}
How to add a comma separated string to an ArrayList? My string could hold 1 or many items which I'd like to add to ArrayList, each item combine with it's own id value separated by underscore (_) so it must be separated arraylist items..
e.g :
string supplierIdWithProducts = "1_1001,1_1002,20_1003,100_1005,100_1006";
ArrayList myArrayList= new ArrayList();
myArrayList.Add("1001,1002"); // 1
myArrayList.Add("1003"); // 20
myArrayList.Add("1005,1006"); // 100
After the ArrayList has been populated, I'd like pass it to a web service
that part is ok for me
foreach (string item in myArrayList){}
How could i do this...
Thanks..
string supplierIdWithProducts = "1_1001,1_1002,20_1003,100_1005,100_1006";
var lookup =
supplierIdWithProducts.Split(',')
.ToLookup(id => id.Split('_')[0],
id => id.Split('_')[1]);
foreach (var grp in lookup)
{
Console.WriteLine("{0} - {1}", grp.Key, string.Join(", ", grp));
}
will print:
1 - 1001, 1002
20 - 1003
100 - 1005, 1006
Firstly, I suggest you try to use a Dictionary or any other generic collection instead of an ArrayList to make it type-safe. Then use a string.Split(char c) and start the processing from there.
Here's an idea on how you can do it. It might get shorter with Extension methods of course. But here's just a thought-process on how you can do it.
static void ParseSupplierIdWithProducts()
{
string supplierIdWithProducts = "1_1001,1_1002,20_1003,100_1005,100_1006";
//eg. [0] = "1_1001", [1] = "1_1002", etc
List<string> supplierIdAndProductsListSeparatedByUnderscore = supplierIdWithProducts.Split(',').ToList();
//this will be the placeholder for each product ID with multiple products in them
//eg. [0] = key:"1", value(s):["1001", "1002"]
// [1] = key:"20", value(s):["1003"]
Dictionary<string, List<string>> supplierIdWithProductsDict = new Dictionary<string, List<string>>();
foreach (string s in supplierIdAndProductsListSeparatedByUnderscore)
{
string key = s.Split('_')[0];
string value = s.Split('_')[1];
List<string> val = null;
//look if the supplier ID is present
if (supplierIdWithProductsDict.TryGetValue(key, out val))
{
if (val == null)
{
//the supplier ID is present but the values are null
supplierIdWithProductsDict[key] = new List<string> { value };
}
else
{
supplierIdWithProductsDict[key].Add(value);
}
}
else
{
//that supplier ID is not present, add it and the value/product
supplierIdWithProductsDict.Add(key, new List<string> { value });
}
}
}
I have a List<T> where T has the property .Next.
The List has the following data:
One
Two
Three
Four
Five
I want to make this:
One.Next = Two;
Two.Next = Three;
Three.Next = Four;
Four.Next = Five;
Five.Next is null as its the last element
One should be assigned to a single Variable of the same type.
How can I do this without lots of ifs/while/hacks ?
UPDATE
The result variable should not be an anonymous type.
I need a return variable of the same type like IEnumerable> or List>
I forgot also to mention that I use an open generic type not a closed one.
sorry for the misinformation!
for(int i = 0;i < list.Count;++i)
list[i].Next = i < list.Count - 1 ? list[i + 1] : null;
You can either use a LinkedList as others have already suggested or ElementAtOrDefault:
var result = list.Select((s,i) => new { This=s, Next=list.ElementAtOrDefault(i+1) });
foreach(var x in result)
Console.WriteLine("{0}.{1}",x.This,x.Next);
Here's the demo: http://ideone.com/Qwiwc
The result variable should not be an anonymous type. I need a return
variable of the same type like IEnumerable> or List> I forgot also to
mention that I use an open generic type not a closed one.
Edit: Here's another approach using a IEnumerable<Tuple<T, T>>:
public static IEnumerable<Tuple<TSource, TSource>> ToLinkedSequence<TSource>(this IEnumerable<TSource> input)
{
return input.Select((x,i) => Tuple.Create(x, input.ElementAtOrDefault(i + 1)));
}
how you would use it:
var sequence = new[] { "One", "Two", "Three", "Four", "Five" };
var linkedSequence = sequence.ToLinkedSequence();
foreach (var x in linkedSequence)
Console.WriteLine("{0}.{1}", x.Item1, x.Item2);
Tuple Class
You can created a LinkedList
List<string> s = new List<string> {"one", "two", "three", "four", "five"};
LinkedList<string> ls = new LinkedList<string>(s);
If you do LinkedList.First you will get LinkedListNode that have the Next set as you desire
public interface INextable<T>
{
public T Next {get;set;}
}
List<MyClass> list = new List<MyClass>(); // Where MyClass implements INextable<MyClass>
var query = list.Zip(list.Skip(1), (a, b) => new
{
First = a,
Second = b
});
foreach (var item in query)
{
item.First.Next = item.Second;
}