for (int z = 0; z < alParmValues.Count; z++)
{
//string[] def;
string[] asd = alParmValues[z].ToString().Split(',');//this is of type string.collections and u cant cast it to a arraylist or array
//if (HUTT.clsParameterValues.bCustomObj == false)
string[] def = alMethSign[z].ToString().Substring(alMethSign[z].ToString().IndexOf('(') + 1, alMethSign[z].ToString().IndexOf(')') - (alMethSign[z].ToString().IndexOf('(') + 1)).Split(',');
}
I have to access both the string arrays outside the loop. Is there a better solution to this? I can't use an ArrayList or declare them as public so how can I access them?
To access something outside of a loop, just declare it outside of the loop, then work with it after your loop processing is done:
string[] arr = ...
for (int z = 0; z < alParmValues.Count; z++)
{
// work with arr...
}
var item = arr[3]; // Accessed outside of loop.
However, there seem to be a few things wrong with your code. I'd recommend thinking a little bit more about the loop body and what you're trying to do there. Consider this line, for example:
for (int z = 0; z < alParmValues.Count; z++)
{
// ...
string[] asd = alParmValues[z].ToString().Split(',');
// There aren't any more references to asd after this point in the loop,
// so this assignment serves no purpose and only keeps its last assigned
// value.
}
This assignment is pointless; every time you go through the loop, you just overwrite the previous value of asd, and you never use it later in the loop.
The scope of both asd and def are limited to the body of the for loop. If you have to access them you need to declare them outside the loop. Is there a problem in putting them out?
Take a look at the Collection Classes Tutorial on MSDN.
Both 'asd' and 'def' are string arrays whose scope is limited to the for loop. You cannot access them outside the loop. If you want to do so, try declaring them outside the for loop.
First, if you want access to the data extracted/computed inside the loop, you must declare a container for the results outside the loop, and then populate its values inside the loop.
Second, don't think about casting the arrays returned from the split method, but rather think about processing their contents.
Assuming that you want the combined results from all elements of the original alParmValues array in a single pair of results, I'd use something like the following pseudo-code. Of course, you'll need to fill in the type for your alParmValues and alMethSign elements, add semicolons, etc. (Because your question didn't explain the content and relationships between the two arrays being processed in your loop, I've just treated them independently.) This isn't complete code, but just a sketch to get you started:
ArrayList allValues = new ArrayList()
foreach (??? parameter in alParmValues) {
foreach (String value in parameter.ToString().Split(',')) {
allValues.add(value)
}
}
ArrayList allMethSignValues = new ArrayList()
foreach (??? methSign in alMethSign) {
String thisString = methSign.toString()
int open = thisString.indexOf('(')
int close = thisString.indexOf(')')
String parenPart = thisString.substring(open + 1, close - open - 1)
foreach (String value in parenPart.split(',')) {
allMethSignValues.add(value)
}
}
Related
This question already has answers here:
Is there an easy way to change a char in a string in C#?
(8 answers)
Closed 5 years ago.
This is kind of a basic question, but I learned programming in C++ and am just transitioning to C#, so my ignorance of the C# methods are getting in my way.
A client has given me a few fixed length files and they want the 484th character of every odd numbered record, skipping the first one (3, 5, 7, etc...) changed from a space to a 0. In my mind, I should be able to do something like the below:
static void Main(string[] args)
{
List<string> allLines = System.IO.File.ReadAllLines(#"C:\...").ToList();
foreach(string line in allLines)
{
//odd numbered logic here
line[483] = '0';
}
...
//write to new file
}
However, the property or indexer cannot be assigned to because it is read only. All my reading says that I have not set a setter for the variable, and I have tried what was shown at this SO article, but I am doing something wrong every time. Should what is shown in that article work? Should I do something else?
You cannot modify C# strings directly, because they are immutable. You can convert strings to char[], modify it, then make a string again, and write it to file:
File.WriteAllLines(
#"c:\newfile.txt"
, File.ReadAllLines(#"C:\...").Select((s, index) => {
if (index % 2 = 0) {
return s; // Even strings do not change
}
var chars = s.ToCharArray();
chars[483] = '0';
return new string(chars);
})
);
Since strings are immutable, you can't modify a single character by treating it as a char[] and then modify a character at a specific index. However, you can "modify" it by assigning it to a new string.
We can use the Substring() method to return any part of the original string. Combining this with some concatenation, we can take the first part of the string (up to the character you want to replace), add the new character, and then add the rest of the original string.
Also, since we can't directly modify the items in a collection being iterated over in a foreach loop, we can switch your loop to a for loop instead. Now we can access each line by index, and can modify them on the fly:
for(int i = 0; i < allLines.Length; i++)
{
if (allLines[i].Length > 483)
{
allLines[i] = allLines[i].Substring(0, 483) + "0" + allLines[i].Substring(484);
}
}
It's possible that, depending on how many lines you're processing and how many in-line concatenations you end up doing, there is some chance that using a StringBuilder instead of concatenation will perform better. Here is an alternate way to do this using a StringBuilder. I'll leave the perf measuring to you...
var sb = new StringBuilder();
for (int i = 0; i < allLines.Length; i++)
{
if (allLines[i].Length > 483)
{
sb.Clear();
sb.Append(allLines[i].Substring(0, 483));
sb.Append("0");
sb.Append(allLines[i].Substring(484));
allLines[i] = sb.ToString();
}
}
The first item after the foreach (string line in this case) is a local variable that has no scope outside the loop - that’s why you can’t assign a value to it. Try using a regular for loop instead.
Purpose of for each is meant to iterate over a container. It's read only in nature. You should use regular for loop. It will work.
static void Main(string[] args)
{
List<string> allLines = System.IO.File.ReadAllLines(#"C:\...").ToList();
for (int i=0;i<=allLines.Length;++i)
{
if (allLines[i].Length > 483)
{
allLines[i] = allLines[i].Substring(0, 483) + "0";
}
}
...
//write to new file
}
Is this the best way to set each item of a string array to that of an Enumerable array? I came up with this approach on my own, I tried to use my google-foo but couldn't really come up with coherent sentences to describe what i'm trying to do here..
string[] adapterDesc = new string[] {};
int i = 0;
foreach(NetworkInterface adapter in adapters)
{
adapterDesc[i] = adapter.Description;
i++;
}
...
No, that code will fail with an IndexOutOfRange exception because you have declared an array of strings that could contain zero elements.
So when you try to set the first element it will crash.
Instead you could use a List where you can add elements dynamically
List<string> adapterDesc = new List<string>();
foreach(NetworkInterface adapter in adapters)
{
adapterDesc.Add(adapter.Description);
}
...
A List is more flexible than an array because you don't have to know before the size of the array and you could still use it like it was an array
for(int x = 0; x < adapterDesc; x++)
{
Console.WriteLine(adapterDesc[x]);
}
If you want to use Linq then you could even reduce your code to a single line with
string[] adapterDesc = NetworkInterface.GetAllNetworkInterfaces()
.Select(ni => ni.Description)
.ToArray();
I'm having a problem in Unity with C#, I'm trying to create a List or Array that has all the information I need.
0000, 0001,0002, etc.
I want to put this into an List/Array and use this information to instantiate a model on a character selection screen. However, this is the part of code where everything starts to get messed up.
I'm just trying to read out the numbers and add them into the list.
void Start () {
gestureListener = this.GetComponent<GestureListener>();
for (int i = 0; i < numberOfModels; i++) {
string b = i.ToString("0000");
List<string> mylist = new List<string>(new string[b]);
Debug.Log (mylist);
break;
}
}
I get this error:
error CS0029: Cannot implicitly convert type `string' to `int'
The error happens on line 5, but to me this seems an to be an irreplaceable line...
The variable B is a string so I wouldn't know why the lists sees it as an int.
Please let me know if you can help, much appreciated!
If you are trying to instantiate a list to then add elements to this list then you got it wrong. You are currently instantiating a new list with just one element every time you iterate. In other words, you are not putting the list to use, you are just creating a new one every time you loop.
Create your List of Strings outside the loop then add to it from inside the loop.
You should have something like this to populate the list.
void Start()
{
List<string> mylist = new List<string>();
gestureListener = this.GetComponent<GestureListener>();
for (int i = 0; i < numberOfModels; i++) {
string b = i.ToString("0000");
myList.Add(b);
Debug.Log (mylist);
break;
}
}
With that said, at the end of your for-loop your myList will have a collection of models per say. You can then iterate that collection to see all the elements you have pushed.
foreach(var item in mylist)
{
//Do whatever with each Item.
}
If you need more examples, take a look at DotNetPerls List Examples
and this video example with Unity in mind.
void Start () {
gestureListener = this.GetComponent<GestureListener>();
List<string> myList = new List<string>();
for (int i = 0; i < numberOfModels; i++) {
string b = i.ToString("0000");
myList.Add(b);
Debug.Log (mylist);
break;
}
//myList is populated with all the numberOfModels here.
}
Don't create a new list inside the loop. The way you are doing it now, you are trying to create a new list (which you throw away anyway), that has progressively larger empty string arrays. For example with a numberOfModels of 100, you would have 100! empty string elements in the list (if you saved it).
Just create a list outside of the for loop, and add the string b to the list inside the loop.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
how to inset a new array to my jagged array
i have a problem, where i dont know how i can make a string array variable in array length.
i have this code now below:
string[] p = new string[10];
int num = 0;
foreach (Product products in GetAllProducts())
{
//do something
p[num]= "some variable result"
num++
}
The problem is, that i dont know how many of "p" i will get, although i know it atleast will be less than 10.
but if i put it on 0, i will get an error when i start it, because it doesn't know the "p[num]"
So i am looking for some way to make "p" have a variable length.
anyone could help me out a bit? thanx
============Solved==========
List<string> p = new List<string>();
int num = 0;
foreach (Product products in GetAllProducts())
{
string s= null;
//do something ( create s out of multiple parts += s etc.)
p.add(s)
num++
}
thanx to solution poster
Use an List<string> instead of an array, if you do not know the number of items you will need to add.
Your array length cannot be modified after it has been instantiated. Use ArrayList or Generic Lists.
var p = new new List<string>(10);
foreach (Product products in GetAllProducts())
{
//do something
p.Add("some variable result");
}
What does GetAllProducts() return? Does it have a count or a length?! You should call that first, save it in a variable, get the count/length and then declare your array!
There's two solution.
If you want to keep using array :
int num = 0;
var list = GetAllProducts();
string[] p = new string[list.Length]; // Or list.Count if this is a collection
foreach (Product products in list)
{
//do something
p[num] = "some variable result";
num++;
}
Otherwise you should use a List like this :
List<string> p = new List<string>();
foreach (Product products in GetAllProducts())
{
//do something
p.Add("some variable result");
}
Use Array.Resize() method, which allows to resize it (by n number of indexes).
In my exmaple I will reize by 1 on each step of the way:
string[] array = new string[3]; //create array
for (int i = 0; i < 5; i++)
{
if (array.Length-1 < i) //checking for the available length
{
Array.Resize(ref array, array.Length + 1); //when to small, create a new index
}
array[i] = i.ToString(); //add an item to array[index] - of i
}
Because your code is using a foreach on the result from GetAllProducts, then GetAllProducts must be returning a IEnumerable collection. Probably the best solution would be to simply assign the result of GetAllProducts to such a collection. For example, perhaps it already returns a list of strings? So you can do:
List<string> strings = GetAllProducts();
There is no need to have a foreach loop to create an array when you already have a collection anyway being returned from GetAllProducts.
Or simply:
var strings = GetAllProducts();
to let the compiler work out the type of strings.
Most things you can do with an array you can also do with a List, and some more (such as adding items to the end of the List).
Perhaps you can post the signature of GetAllProducts (especially its return type) so we can better advise you?
I see many gave you the right answer which is the use of Lists. If you still need an array in the end, you can easily convert your list into an Array like this :
string[] tempArray = myList.ToArray();
Is there a way to iterate ValueCollection using straight for loop? (not foreach)
e.g.
Dictionary<string, List<long>>.ValueCollection somevalues = somecollection.Value.Values;
for(int i = 0; i< somevalues.Count; i++)
{
//now what?
}
No - there's no indexer or anything similar for ValueCollection. I suppose you could use:
for (int i = 0; i < someValues.Count; i++)
{
var item = someValues.ElementAt(i);
...
}
but that would perform like a dog :) (Just iteration would be O(n^2), as it would be like Schlemiel the Painter.)
Why do you want to do this? If you want items with elements, just keep a counter or use the overload of Select that passes in the index as well as the item.
You don't have to use an index in a for loop...
for (var en = somevalues.GetEnumerator(); en.MoveNext(); )
{
var item = en.Current;
// do something useful...
}
not out of the box. some collections do not have index operators ( myCollection[ someIndex ] )
Your most likely reason for wanting this is to be able to use that index in some other way. Simply stick with a foreach loop, initialize a variable to zero before the loop and increment it at the bottom of the loop.