Is there any way to initialize several variables from one array? [duplicate] - c#

This question already has answers here:
c# multi assignment
(7 answers)
Closed 8 years ago.
In some languages it is possible to initialize several variables at the same time from an array.
For example in PHP you can do something like this:
$array = array('a', 'b', 'c');
list($a, $b, $c) = $array;
Is it possible to do this in C# as well?
I want to apply this on a program where I read all lines from a file where I know every line is two words only (never more, never less).
I know I can create the function myself (and sending in variables by reference with outkeyword) but I would like to know if any built in functionality exists for it.
I would like to know this mostly for the reason that if it is possible the code might be more readable for other developers.

In C#,
string[] arr1 = new string[] { "one", "two", "three" };
string s1 = arr1[0];
string s2 = arr1[1];
string s3 = arr1[2];

If readability is the issue and if I understand you correctly - I don't know of an in-built way. But you can create a function for that.
void Doit(out string one, out string two, string[] input)
{
one = input[0];
two = input[1];
}
And use it thus:
string[] s = new string[] { "First", "Second" };
string a, b;
Doit(out a, out b, s);
I just realized that you don't need my answer. (I had initially understood "I know I can create the function myself..." differently.) Perhaps, though, it can help someone else.

char[] array = new char[] {'a','b','c'};

As far as I know there is no buit-in way to do that.
Maybe a good way to implement that functionality is by using extension methods in order to improve readability.
Simply write the needed code in a extension method that can be attached to the type you want to initialize like a list in your example above and take an array as input to that function:
public static class Extensions {
public static void initFromArray<T> (this List<T> list, T[] array) {
for (int i = 0; i < array.Length; i++) {
list[i] = array[i];
}
}
}
Then you can use this method for example like in the following:
int[] array = new int [] { 1, 4, 6, 2, 5 };
List<int> list = new List<int>();
for (int i = 0; i < 4; i++) list.Add(0);
list.initFromArray<T>(array);

Related

Reverse an Array order and print it C# [duplicate]

This question already has answers here:
How to reverse an array using the Reverse method. C# [closed]
(6 answers)
Closed 6 months ago.
using System;
using System.Linq;
namespace Array.ReversingArrayChar
{
class Program
{
static void Main(string[] args)
{
string input = Console.ReadLine();
char[] symbol = input.Split(' ').Select(char.Parse).ToArray();
symbol.Reverse();
for (int a = 0; a <= symbol.Length - 1; a++)
{
Console.Write(symbol[a] + " ");
}
}
}
}
When I run the code I get the Array printed but not in reversed order even tho I used .Reverse(). It's probably a really simple mistake but it's too late at night for my brain to figure it out.
Enumerable.Reverse is a LINQ extension that returns the sequence reversed, so you have to assign it to a variable. But here you want to use Array.Reverse:
Array.Reverse(symbol);
Use Enumerable.Reverse if you don't want to modify the original collection and if you want to support any kind of sequence. Use List.Reverse or Array.Reverse if you want to support only these collections and you want to modify it directly. Of course this is more efficient since the method knows the size and you need less memory.
Oh Man..! you are almost there, your code is fine but you need to use the output of the .Reverse() method. since the method won't modify the actual collection, it will return the reversed array. you can try the following:
string input = "A S D R F V B G T";
char[] symbols = input.Split(' ').Select(char.Parse).ToArray();
foreach (var symbol in symbols.Reverse())
{
Console.Write(symbol + " ");
}
You will get the output as T G B V F R D S A

C# how to make it so that a function that can sort strings or ints without overloading? [duplicate]

This question already has answers here:
creating a generic sort method
(2 answers)
Closed 4 years ago.
As the title says, I had to write some code to sort either array/list of strings or integers. My OOP knowledge is really rusty since I haven't used C#/Java for a long while.
Is there a way to make it so I just need to code one function so that I don't have to overload the function
(e.g InsertSort(int [] arr) and InsertSort(string [] arr))
I heard something about using IComparable or Comparator and I took a look at the documentation of both but they seems to me that those are like more for Objects.
Thanks for any help!
Generic methods should be your friend here. Generics allow you to defer the specification of types used in method until actually used in program. You can read more on Generic here.
public T[] InsertSort<T>(T[] source)
{
// Do something
}
This can be invoked using strings/int arrays as following.
var intArray = new int[]{1,2,3};
var stringArray = new string[]{"1","2","3"};
InsertSort(intArray);
InsertSort(stringArray);
To get started, you might try something like this method.
public static IEnumerable<T> InsertSort<T>(IEnumerable<T> tmp)
{
//... Perform sorting
//... Return the sorted results as IEnumerable
}
You'll be able to send in a list or an array of the types you choose.
Usage:
List<int> listA = new List<int>();
var sortedListA = InsertSort(listA);
string[] arrA = new string[5];
var sortedArrayA = InsertSort(arrA);

How to reverse string in C# [duplicate]

I didn't get the problem - I was trying to do a simple action:
for(i = x.Length-1, j = 0 ; i >= 0 ; i--, j++)
{
backx[j] = x[i];
}
Both are declared:
String x;
String backx;
What is the problem ? It says the error in the title...
If there is a problem - is there another way to do that?
The result (As the name 'backx' hints) is that backx will contain the string X backwards.
P.S. x is not empty - it contains a substring from another string.
Strings are immutable: you can retrieve the character at a certain position, but you cannot change the character to a new one directly.
Instead you'll have to build a new string with the change. There are several ways to do this, but StringBuilder does the job in a similar fashion to what you already have:
StringBuilder sb = new StringBuilder(backx);
sb[j] = x[i];
backx = sb.ToString();
EDIT: If you take a look at the string public facing API, you'll see this indexer:
public char this[int index] { get; }
This shows that you can "get" a value, but because no "set" is available, you cannot assign values to that indexer.
EDITx2: If you're looking for a way to reverse a string, there are a few different ways, but here's one example with an explanation as to how it works: http://www.dotnetperls.com/reverse-string
String is immutable in .NET - this is why you get the error.
You can get a reverse string with LINQ:
string x = "abcd";
string backx = new string(x.Reverse().ToArray());
Console.WriteLine(backx); // output: "dcba"
String are immuatable. You have convert to Char Array and then you would be able to modify.
Or you can use StringBuilder.
for example
char[] wordArray = word.ToCharArray();
In C# strings are immutable. You cannot "set" Xth character to whatever you want. If yo uwant to construct a new string, or be able to "edit" a string, use i.e. StringBuilder class.
Strings are immutable in C#. You can read more about it here: http://msdn.microsoft.com/en-us/library/362314fe.aspx
Both the variables you have are string while you are treating them as if they were arrays (well, they are). Of course it is a valid statement to access characters from a string through this mechanism, you cannot really assign it that way.
Since you are trying to reverse a string, do take a look at this post. It has lot of information.
public static string ReverseName( string theName)
{
string revName = string.Empty;
foreach (char a in theName)
{
revName = a + revName;
}
return revName;
}
This is simple and does not involve arrays directly.
The code below simply swaps the index of each char in the string which enables you to only have to iterate half way through the original string which is pretty efficient if you're dealing with a lot of characters. The result is the original string reversed. I tested this with a string consisting of 100 characters and it executed in 0.0000021 seconds.
private string ReverseString(string testString)
{
int j = testString.Length - 1;
char[] charArray = new char[testString.Length];
for (int i = 0; i <= j; i++)
{
if (i != j)
{
charArray[i] = testString[j];
charArray[j] = testString[i];
}
j--;
}
return new string(charArray);
}
In case you need to replace e.g. index 2 in string use this (it is ugly, but working and is easily maintainbable)
V1 - you know what you want to put their. Here you saying in pseudocode string[2] = 'R';
row3String.Replace(row3String[2], 'R');
V2 - you need to put their char R or char Y. Here string[2] = 'R' if was 'Y' or if was not stay 'Y' (this one line if needs some form of else)
row3String.Replace(row3String[2], row3String[2].Equals('Y') ? 'R' : 'Y');

Having two param lists with same size

The method PrintTimes(string a, int b) prints the string a, b times (i.e. PrintTimes("test",3) will print testtesttest).
I want to create a method, which will get a params array of strings and a params array of integers. So the call function will ook like this
PrintTimes("A","B","C","D",2,1,3,2);
Or
PrintTimes("A",2,"B",1,"C",3,"D",2)
Both of which will print AABCCCDD
Since there can be only one params parameter in a method, this is impossible. So is there a way to do this?
I know I can create a Class with a string and an int variable, and create a params array for the class. But I'd rather not, since it would involve constructing a new Class for each set
Why not using a class
public class PrintParameter
{
public int Count {get;set;}
public string Content{get;set;}
}
Then
public void PrintTimes(List<PrintParameter> inputs)
{
//for each input print the "Content", "Count" times
}
Or
public void PrintTimes(params PrintParameter[] inputs)
{
//for each input print the "Content", "Count" times
}
If you don't want to define a class you may try something like List<KeyValuePair<string,int>> or other alternatives such as List<Tuple<string,int>> and etc. However the preferred way of doing is to use a class with meaningful properties.
How about just dropping the params keyword and taking arrays instead? That is, make the signature PrintTimes(string[], int[]). PrintTimes(new[]{"A","B","C","D"}, new[]{2,1,3,2}); isn't that much more to write.
There are several ways you can go about solving this problem. While you can only have one params, you can just make both your parameters arrays:
PrintTimes(string[] strings, int[] printCounts)
{
// Assert strings.Length == printCounts.Length
for (int i = 0; i < strings.Length; i++)
{
for (int j = 0; j < printCounts[i]; j++)
{
// Print strings[i]
}
}
}
Then it can be called like this:
int[] numbers = new int[3] {1, 2, 3};
string[] names = new string[3] {"Matt", "Joanne", "Robert"};
PrintTimes(names, numbers);
Following up on Hossein's suggestion, why not something as simple as:
void PrintTimes(List<String> strings, List<Int> count)
(or do it as an array as the comments said) Then inside PrintTimes require the inputs to be the same length or some logical fail when they don't.

Get a string to reference another in C#

I'm coming from a C++ background. This question has been asked before, but try as I might I cannot find the answer. Let's say I have:
string[] ArrayOfReallyVeryLongStringNames = new string[500];
ArrayOfReallyVeryLongStringNames[439] = "Hello world!";
Can I create a string that references the above (neither of these will compile):
string a = ref ArrayOfReallyVeryLongStringNames[439]; // no compile
string a = &ArrayOfReallyVeryLongStringNames[439]; // no compile
I do understand that strings are immutable in C#. I also understand that you cannot get the address of a managed object.
I'd like to do this:
a = "Donkey Kong"; // Now ArrayOfReallyVeryLongStringNames[439] = "Donkey Kong";
I have read the Stack Overflow question Make a reference to another string in C#
which has an excellent answer, but to a slightly different question. I do NOT want to pass this parameter to a function by reference. I know how to use the "ref" keyword for passing a parameter by reference.
If the answer is "You cannot do this in C#", is there a convenient workaround?
EDIT:
Some of the answers indicate the question was unclear. Lets ask it in a different way. Say I needed to manipulate all items in the original long-named array that have prime indices. I'd like to add aliases to Array...[2], Array...[3], Array...[5], etc to a list. Then, modify the items in the list using a "for" loop (perhaps by passing the list just created to a function).
In C# the "using" keyword creates an alias to a class or namespace. It seems from the answers, that it is not possible to create an alias to a variable, however.
You could create a wrapper that keeps a reference to the underlying array AND the index of the string:
public sealed class ArrayStringReference
{
private readonly string[] _array;
private readonly int _index;
public ArrayStringReference(string[] array, int index)
{
_array = array;
_index = index;
}
public string Value
{
get
{
return _array[_index];
}
set
{
_array[_index] = value;
}
}
public override string ToString()
{
return Value;
}
}
Then this will work:
string[] ArrayOfReallyVeryLongStringNames = new string[500];
ArrayOfReallyVeryLongStringNames[439] = "Hello world!";
var strRef = new ArrayStringReference(ArrayOfReallyVeryLongStringNames, 439);
Console.WriteLine(ArrayOfReallyVeryLongStringNames[439]); // Outputs "Hello world!"
strRef.Value = "Donkey Kong";
Console.WriteLine(ArrayOfReallyVeryLongStringNames[439]); // Outputs "Donkey Kong"
You could make this more convenient to use by providing an implicit string operator so you don't have to use .Value to access the underlying string:
// Add this to class ArrayStringReference implementation
public static implicit operator string(ArrayStringReference strRef)
{
return strRef.Value;
}
Then instead of having to access the underlying string like this:
strRef.Value = "Donkey Kong";
...
string someString = strRef.Value;
You can do this:
strRef.Value = "Donkey Kong";
...
string someString = strRef; // Don't need .Value
This is just syntactic sugar, but it might make it easier to start using an ArrayStringReference in existing code. (Note that you will still need to use .Value to set the underlying string.)
The closest you can get is this:
unsafe
{
string* a = &ArrayOfReallyVeryLongStringNames[439]; // no compile
}
Which gives an exception:
Cannot take the address of, get the size of, or declare a pointer to a managed type ('string')
So no, not possible...
Also read this MSDN article which explains what types can be used (blittable types).
When I do something like this in C#:
string a = "String 1";
string b = a;
a = "String 2";
Console.WriteLine(a); // String 2
Console.WriteLine(b); // String 1
The thing is, both "String 1" and "String 2" literals are created at the start of the program, and strings are always pointers: at first a references "String 1" literal and afterwards it references "String 2". If you want them to always reference the same thing, in C# you just use the same variable.
The string objects themselves are immutable in C#:
Because a string "modification" is actually a new string creation, you must use caution when you create references to strings. If you create a reference to a string, and then "modify" the original string, the reference will continue to point to the original object instead of the new object that was created when the string was modified.
When the string mutability is needed, for example, to concatenate a lot of strings faster, other classes are used, like StringBuilder.
To sum it up, what you're trying to do is impossible.
In C#, a String is an Object. Therefore String a = "Donkey Kong" says that a now have a reference to this string that is being allocated over the memory. Then all you need to do is:
ArrayOfReallyVeryLongStringNames[439] = a;
And that will copy the refrence (which you should be thinking of in C#!!!) to the location in the string.
BUT!! When you do a="new string";, a will get a new reference. See the example I made:
http://prntscr.com/3kw18v
You can only do this with unsafe mode.
You could create a wrapper
public class StringWrapper
{
public string Value {get;set;}
}
StringWrapper[] arrayOfWrappers = new StringWrapper[500];
arrayOfWrappers[439] = new StringWrapper { Value = "Hello World" };
StringWrapper a = arrayOfWrappers[439];
a.Value = "New Value";
What you are trying to do is universally discouraged, and actively prevented, in C#, where the logic should be independent of the memory model, however, refer to related SO question C# memory address and variable for some info.
EDIT 1
A more canonical approach to your actual problem in C# would be:
// using System.Linq;
string[] raw = new string[] { "alpha", "beta", "gamma", "delta" };
List<int> evenIndices = Enumerable.Range(0, raw.Length)
.Where(x => x % 2 == 0)
.ToList();
foreach (int x in evenIndices)
raw[x] = raw[x] + " (even)";
foreach (string x in raw)
Console.WriteLine(x);
/*
OUTPUT:
alpha (even)
beta
gamma (even)
delta
*/
If you really want to modify the original memory structure itself, then perhaps C++ is a more appropriate language choice for the solution.
EDIT 2
Looking around on SO, you may want to look at this answer Hidden Features of C#? to an unrelated question.
[TestMethod]
public void TestMethod1()
{
string[] arrayOfString = new string[500];
arrayOfString[499] = "Four Ninty Nine";
Console.WriteLine("Before Modification : {0} " , arrayOfString[499]);
string a = arrayOfString[499];
ModifyString(out arrayOfString[499]);
Console.WriteLine("after a : {0}", a);
Console.WriteLine("after arrayOfString [499]: {0}", arrayOfString[499]);
}
private void ModifyString(out string arrayItem)
{
arrayItem = "Five Hundred less one";
}
Of course you can, hehe:
var a = __makeref(array[666]);
__refvalue(a, string) = "hello";
But you would have to have a very good reason to do it this way.

Categories