I have the following array:
string[] list1 = new string[2] { "01233", "THisis text" };
string[] list2 = new string[2] { "01233", "THisis text" };
string[] list3 = new string[2] { "01233", "THisis text" };
string[] list4 = new string[2] { "01233", "THisis text" };
string[][] lists = new string[][] { list1, list2, list3, list4 };
I am trying to see the array values using the following code:
for (int i = 0; i < lists.GetLength(0); i++)
{
for (int j = 0; j < lists.GetLength(1); j++)
{
string s = lists[i, j]; // the problem is here
Console.WriteLine(s);
}
}
Console.ReadLine();
The problem is lists[i, j]; is underlined and causing this error message : Wrong number of indices inside []; expected '1'
Could you please tell me how to solve this problem ?
lists is not a 2D array. It is an array of arrays. Hence the syntax lists[i][j].
for (int i = 0; i < lists.Length; i++)
{
for (int j = 0; j < lists[i].Length; j++)
{
string s = lists[i][j]; // so
Console.WriteLine(s);
}
}
Console.ReadLine();
Note how Length is checked for an array of arrays. However, as others have said, why not use foreach? You need two nested foreach loops for an array of arrays.
Another option is to actually use a 2D array, a string[,]. Declared like:
string[,] lists = { { "01233", "THisis text" },
{ "01233", "THisis text" },
{ "01233", "THisis text" },
{ "01233", "THisis text" }, };
Then you can use two for loops like you have, with lists[i,j] syntax, or one single foreach.
Because you have list of lists and not 2D array. To get element from your datastructure you have to use it like this:
lists[i][j]
and your full code would be:
for (int i = 0; i < lists.Length; i++)
{
for (int j = 0; j < lists[i].Length; j++)
{
string s = lists[i][j];
Console.WriteLine(s);
}
}
Console.ReadLine();
But actually, in your case it's better to use foreach:
foreach (var l in lists)
{
foreach (var s in l)
{
Console.WriteLine(s);
}
}
Console.ReadLine();
Try to use this
for (int i = 0; i < lists.Length; i++)
{
for (int j = 0; j < lists[i].Length; j++)
{
string s = lists[i][j];
Console.WriteLine(s);
}
}
Console.ReadLine();
Use foreach instead
foreach(var array in lists )
foreach(var item in array)
{
//item
}
Related
I created a sort method that takes in a string array and sorts it alphabetically. However, I made a void method, not thinking about the fact that I can't really write a void method's data to a file, which is what I am trying to do. So now I am having trouble converting my method to a string array method as opposed to the void method. Can someone please point me in the right direction?
public void Sort(String[] arr)
{
String temp = "";
for (int i = 0; i < arr.Length; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i].CompareTo(arr[j]) > 0)
{
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
Console.WriteLine(arr[i]);
}
}
updated code with my call to method:
class InsertionSort
{
public static string[] Sort(String[] arr)
{
String temp = "";
for (int i = 0; i < arr.Length; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i].CompareTo(arr[j]) > 0)
{
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
return arr;
}
}
}
class Program
{
static void Main(string[] args)
{
String[] words = File.ReadLines("jumbled english FILTERED.ALL.txt").ToArray();
String[] sortedWords = InsertionSort.Sort(words);
System.IO.File.WriteAllLines("sortedtext.txt", sortedWords);
}
}
}
my code
what it prints
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
String[] arr = new String[3];
arr[0] = "B";
arr[1] = "C";
arr[2] = "A";
Console.WriteLine(arr[0]);
Console.WriteLine(arr[1]);
Console.WriteLine(arr[2]);
Sort(arr);
Console.WriteLine(arr[0]);
Console.WriteLine(arr[1]);
Console.WriteLine(arr[2]);
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\Test\Result.txt"))
{
foreach (string str in arr)
{
file.WriteLine(str);
}
}
Console.ReadLine();
}
public static void Sort(String[] arr)
{
String temp = "";
for (int i = 0; i < arr.Length; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i].CompareTo(arr[j]) > 0)
{
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
//Console.WriteLine(arr[i]);
}
}
}
}
Result :
Ben,
Let me try to answer your question in two parts.
First, you wanted to return values from the method. For this, you need to change the return Type to string[] and return the arr after processing
public string[] Sort(string[] arr)
{
string temp = "";
for (int i = 0; i < arr.Length; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[i].CompareTo(arr[j]) > 0)
{
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
return arr;
}
Second part, you mentioned in comment that you want to write this to a file. You can use System.IO.File.WriteLineAllLines method to write to a file.
var input = new []{ "First line", "Third line" , "Second line" };
string[] lines = Sort(input);
System.IO.File.WriteAllLines(#"OutputFile.txt", lines);
To read more on writing contents to a file, please refer
Why make your own sorter and not use Array.Sort?
var lines = new[] { "one", "two", "three", "four" };
Array.Sort(lines, StringComparer.Ordinal);
System.IO.File.WriteAllLines("file.txt", lines);
I don't know why you creating such method as we have already linq to do such thing.
You can do this way. I hope it will work for you.
string[] words = { "India", "England", "America", "China", "Australia" };
string[] Ascending = words.OrderBy(c => c).Select(c=>c).ToArray(); // Ascending order
string[] Descending = words.OrderByDescending(c => c).Select(c => c).ToArray(); // Ascending order
foreach (var item in Ascending)
{
Console.WriteLine(item);
}
foreach (var item in Descending)
{
Console.WriteLine(item);
}
I have a problem retrieving values in the order that I want
I wrote a simple code to demonstrate :
List<string> st1 = new List<string>() {"st11","st12"};
List<string> st2 = new List<string>() {"st21","st22"};
ArrayList stringArrayList = new ArrayList();
stringArrayList.Add(st1);
stringArrayList.Add(st2);
string[] n1 = new string[10];
int i = 0;
foreach (List<string> item in stringArrayList)
{
foreach (var item2 in item)
{
n1[i] = item2;
i++;
}
}
in this code the output will be : st11,st12 st21,s22
i want it to get values like this : st11,st21 st12,st22
i want the information stored in this order "st11,st21 st12,st22" into n1
If the lenght of the list are the same you can make something like this:
int j = 0;
int lengthToLoop = st1.length;
for(int i = 0; i < lengthToLoop; i++)
{
n1[j++] = st1[i];
n1[j++] = st2[i];
}
If the length are not equal you can calculate the minimum, copy the minimum length of element from each and then copy the remaining.
Here's an implementation that will do what you're looking for, and will also handle jagged arrays.
List<string> st1 = new List<string>() { "st11", "st12" };
List<string> st2 = new List<string>() { "st21", "st22", };
ArrayList stringArrayList = new ArrayList();
stringArrayList.Add(st1);
stringArrayList.Add(st2);
//this will protect us against differing max indexes if the 2D array is jagged.
int maxIndex = 0;
int totalElements = 0;
foreach (List<string> currentList in stringArrayList)
{
if (currentList.Count > maxIndex)
{
maxIndex = currentList.Count;
}
totalElements += currentList.Count;
}
string[] n1 = new string[totalElements];
int i = 0;
for (int j = 0; j < maxIndex; j++)
{
for (int k = 0; k < stringArrayList.Count; k++)
{
List<string> currentStringArray = (List<string>)stringArrayList[k];
if (j < currentStringArray.Count)
{
n1[i] = currentStringArray[j];
i++;
}
}
}
You have to reverse the two loops, making the outer loop the inner loop.
Use a for loop instead of a foreach loop for the outer loop using the length of the string arrays as the delimiter.
Also: Don't use ArrayList, but a real typed list.
List<string> st1 = new List<string>() { "st11", "st12" };
List<string> st2 = new List<string>() { "st21", "st22" };
List<List<string>> stringArrayList = new List<List<string>>();
stringArrayList.Add(st1);
stringArrayList.Add(st2);
// Get length of first string array
int firstArrayLength = stringArrayList[0].Count;
string[] n1 = new string[10];
int i = 0;
// For each position in the arrays from 0 to firstArrayLength -1 do
for (int arrayPosition = 0; arrayPosition < firstArrayLength; arrayPosition++)
{
// For each of the string array
foreach (var stringArray in stringArrayList)
{
// Get the item from the stringArray at position arrayPosition
n1[i] = stringArray[arrayPosition];
i++;
}
}
First, check the max list length, and then take item at index (0,1,3... till max) from every list. Don't forget to check if the index exist. In addition, you can set the exact size of n1 because it is the sum of all list count. You don't need to have a separated line for i++ in this case.
List<string> st1 = new List<string> { "st11", "st12" };
List<string> st2 = new List<string> { "st21", "st22" };
List<List<string>> stringArrayList = new List<List<string>> {st1, st2};
int maxCount = stringArrayList.Max(x => x.Count);
int totalItems = 0;
stringArrayList.ForEach(x=> totalItems+= x.Count);
string[] n1 = new string[totalItems];
int i = 0;
for (int index = 0; index < maxCount; index++)
{
foreach (var list in stringArrayList)
{
if (list.Count > index)
{
n1[i++] = list[index];
}
}
}
If I got an array like:
string[] test = new string[5] { "hello", "world", "test", "world", "world"};
How can I make a new array out of the ones that is the same string, "world" that is where you on before hand know how many there are, here 3?
I was thinking of something like:
string[] newArray = new string[3];
for (int i = 0; i < 5; i++)
{
if (test[i].Contains("world"))
{
newArray[i] = test[i];
}
}
The problem is here: newArray[i] = test[i];
Since it's iterating from 0 to 4, there's gonna be an error since newArray is limited to 3.
How do solve this?
EDIT: I need it to be that from test (the old array) position 1, 3 and 4 should be stored at 0, 1 and 2 in the newArray.
You want to use Linq:
var newArray = test.Where(x => x.Contains("world")).ToArray();
Use a List<string> instead:
List<string> newList = new List<string>();
for (int i = 0; i < 5; i++)
{
if (test[i].Contains("world"))
{
newList.Add(test[i]);
}
}
If you really need it as an array later.. convert the list:
string[] newArray = newList.ToArray();
You are using the same index i for both test and newArray. I would suggest you create another counter variable and increment it:
string[] newArray = new string[3];
int counter = 0;
for (int i = 0; i < 5; i++)
{
if (test[i].Contains("world"))
{
newArray[counter] = test[i];
counter++;
}
}
This isn't technically your question but if you wish to make a load of arrays based of those with the same word you could do
test.GroupBy(x => x).ToList();
this will give you a List of Lists.. with your test data this will be
list1 - hello
list2 - world world world
list3 - test
Example use
var lists = test.GroupBy(x => x).ToList();
foreach(var list in lists)
{
foreach(var str in list)
{
Console.WriteLine(str);
}
Console.WriteLine();
}
With an extra helper index variable
string[] newArray = new string[3];
for (int i = 0, j = 0; i < 5; i++)
{
if (test[i].Contains("world"))
{
newArray[j++] = test[i];
if (j >= newArray.Length)
break;
}
}
How would I go about generating a list of all combinations of words up to a certain length from a List<string> source?
For example, I have a List<string> of 10,600+ words which I need to convert to a List<List<string>>, however, the sub list only needs to contain combinations up to and including a given maximum length, for this example, I'll say 3.
I don't care about the order in which the words appear in the sub list. For example, I only need 1 of the following in the list:
"laptop", "computer", "reviews"
"laptop", "reviews", "computer"
"computer", "laptop", "reviews"
"computer" "reviews", "laptop"
"reviews", "computer", "laptop"
"reviews", "laptop", "computer"
Is it even possible given the large number of combinations I would need to generate?
Any help is much appreciated.
First of all, I'm not sure that you really want to generate such huge list. If you really do, then I suggest you to consider to use iterators for lazy list generation instead of this huge list:
static void Main()
{
var words = new List<string> {"w1", "w2", "w3", "w4", "w5", "w6", "w7"};
foreach (var list in Generate(words, 3))
{
Console.WriteLine(string.Join(", ", list));
}
}
static IEnumerable<List<string>> Generate(List<string> words, int length, int ix = 0, int[] indexes = null)
{
indexes = indexes ?? Enumerable.Range(0, length).ToArray();
if (ix > 0)
yield return indexes.Take(ix).Select(x => words[x]).ToList();
if (ix > length)
yield break;
if (ix == length)
{
yield return indexes.Select(x => words[x]).ToList();
}
else
{
for (int jx = ix > 0 ? indexes[ix-1]+1 : 0; jx < words.Count; jx++)
{
indexes[ix] = jx;
foreach (var list in Generate(words, length, ix + 1, indexes))
yield return list;
}
}
}
Hopefully I didn't mess with anything.
for(int i = 0; i < list.Count; i ++)
{
list1 = new List<string> { list[i] };
listcombinations.Add(list1);
for(int j = i + 1; j < list.Count; j ++)
{
list1 = new List<string> { list[i], list[j] };
listcombinations.Add(list1);
for(int k = j + 1; k < list.Count; k ++)
{
list1 = new List<string> { list[i], list[j], list[k] };
listcombinations.Add(list1);
}
}
}
i suppose the problem is mostly to check if a combination of words exists already in the list:
what you can do for that:
//generate a dictionary with key hashcode / value list of string
Dictionary<int, List<string>> validCombinations= new Dictionary<int, List<string>>();
//generating anyway your combinations (looping through the words)
List<string> combinationToCheck = new List<string>(){"reviews", "laptop", "computer"};
//sort the words
combinationToCheck.Sort();
string combined = String.Join("", combinationToCheck.ToArray());
//calculate a hash
int hashCode = combined.GetHashCode();
//add the combination if the same hash doesnt exist yet
if(!validCombinations.ContainsKey(hashCode))
validCombinations.Add(hashCode, combinationToCheck);
private List<List<string>> GetCombinations()
{
List<List<string>> mResult= new List<List<string>>();
for (int i = 0; i < mList.Count; i++)
{
for (int k = 0; k < mList.Count; k++)
{
if (i == k) continue;
List<string> tmpList = new List<string>();
tmpList.Add(mList[i]);
int mCount = 1;
int j = k;
while (true)
{
if (j >= mList.Count) j = 0;
if (i != j)
{
tmpList.Add(mList[j]);
mCount++;
}
j += 1;
if (mCount >= mList.Count) break;
}
mResult.Add(tmpList);
}
}
return mResult;
}
I have a list of names and phone numbers like so:
var phonelist = List<string[]>
{
new string[] {"Bill", "1234", "12345", "12314" },
new string[] {"Bob", "", "12345", "12314" },
new string[] {"Chris", "", "", "12314" },
new string[] {"Dave", "1234", "", "12314" },
new string[] {"Andy", "1234", "12345", "" },
}
What is the most efficient/elegant way to process this list so that the 'empty' numbers get filled from the right ?
Note, the arrays should stay the same length, like so:
var phonelist = List<string[]>
{
new string[] {"Bill", "1234", "12345", "12314" },
new string[] {"Bob", "12345", "12314", "" },
new string[] {"Chris", "12314", "", "" },
new string[] {"Dave", "1234", "12314", "" },
new string[] {"Andy", "1234", "12345", "" },
}
for each array cell, check if its empty and swap it with cell+1, if it's still empty swap it with cell+2.. when cell becomes not empty do the same thing with cell+2...
int j;
foreach (string[] strs in phoneList)
{
for (int i = 0; i < strs.Length; i++)
{
j = 1;
while (string.IsNullOrEmpty(strs[i]) && j < strs.Length - i)
{
if (!string.IsNullOrEmpty(strs[i + j])) // to not swap 2 empty strings
{
strs[i] = strs[i + j];
strs[i + j] = "";
}
j++;
}
}
}
public static void PutEmptyStringsToTheEnd(string[] array) {
int j = 0;
for (int i = 0; i < array.Length; ++i)
if (array[i].Length > 0)
array[j++] = array[i];
while (j < array.Length)
array[j++] = "";
}
Call this function for each List element.
simple and ugly :(
for(var x=0;x<phonelist.Count;x++)
{
var strings = phonelist[x];
var l = strings.Length;
var newAr=new string[l];
var k = 0;
for (var i = 0; i < l; )
{
if(strings[i]!="")
{
newAr[k++] = strings[i];
}
i++;
}
for (; k < l; k++)
newAr[k] = "";
phonelist[x] = newAr;
}
You could do something like that :
Comparison<string> comparison = (x,y) =>
{
if (String.IsNullOrEmpty(x))
return 1;
if (String.IsNullOrEmpty(y))
return -1;
return String.Compare(x,y);
}
foreach (string[] array in phoneList)
{
Array.Sort(array, comparison);
}
However you will need to tune the comparison logic a bit to keep the names before the numbers
EDIT : since the name seems to always be the first element, another option is to exclude it from the sort. No Array.Sort overload takes a Comparison<T> and a range, so you have to use a IComparer<T> instead :
class MyComparer : IComparer<string>
{
public int Compare(string x, string y)
{
if (String.IsNullOrEmpty(x))
return 1;
if (String.IsNullOrEmpty(y))
return -1;
return String.Compare(x,y);
}
}
foreach (string[] array in phonelist)
{
Array.Sort(array, 1, array.Length - 1, new MyComparer());
}
This should work. I'm not that knownledged at C#, but the idea is there
foreach(string[] person in phonelist)
{
string[] newPerson = {"","","",""};
int index = 0;
for(int i=0; i<4; i++)
{
if(!String.IsNullOrEmpty(person[i])) newPerson[index++] = person[i];
}
person = newPerson;
}
This is cooler
List<string[]> result = phonelist.Select(per => per.OrderBy(txt=>txt.Length==0).ToArray()).ToList();
List<string[]> sorted = new List<string[]>();
foreach (string[] entry in phoneList)
{
List<string> nonEmpty = (from s in entry
where String.IsNullOrEmpty(s) == false
select s).ToList();
int pad = entry.Length - nonEmpty.Count;
List<string> pads = new List<string>();
while (pad > 0)
{
pads.Add(String.Empty);
--pad;
}
List<string> sortedEntry = new List<string>();
sortedEntry.AddRange(nonEmpty);
sortedEntry.AddRange(pads);
sorted.Add(sortedEntry.ToArray());
}