Add two list data into array while using if condition - c#

I have two lists, one list have some record (not known specific no of rec, but not more than 13 records) and second list have only empty value. I am using if condition on these two list. And want to add these two list in one array. I am using this code:
for (int i=0; i>12; i++)
{
List<string> excList = new List<string>();
//added column from table, which can varies
excList.Add((string)column.ColumnName);
string[] excelList = new string[] { };
List<string> stack = Enumerable.Range(excList.Count, 13)
.Select(z => string.Empty)
.ToList<string>();
if (excList.Count > i)
{
excelList = excList.ToArray();
}
if (excList.Count <= i)
{
excelList = stack.ToArray();
}
eCol0 = excelList[0].ToString();
//show first value, after adding two list in excelList
response.Write(eCol0);
}
Using this code, when the second condition started and list (excList) is adding in array (excelList) then excelList is showing only second list data.
I want to insert these two list (excList and stack) into arrayList (which have range of 13).But these two list must add on the bases of if condition as I'm using if condition in above code.

Well you never Add something to your string array excelList. You always assign it new.
Using an array is also not the best for adding values, since you need to know beforehand the size of the array.
If you really want an array in the end with both results, you should do something like this:
List<string> excList = new List<string>();
... fill your excList here and initialize the stack list with whatever you need ...
excList.AddRange(stack);
string[] excelList = excList.ToArray();
Edit: as the comments mention, your question is a little bit confusing and you are using one big loop with no clear reason why and adding empty values makes no sence too... so i tried to get the essence out of what you wanted to know
Edit:2
Wait a second, I think you want in the end, an array of strings, with the size of 13, where the elements are at least string.empty
List<string> excList = new List<string>();
//added column from table, which can varies
excList.Add((string)column.ColumnName);
string[] excelList = new string[13];
for (int i = 0; i < excList.Count; i++)
{
excelList[i] = excList[i];
}
for (int i = excList.Count; i < 13; i++)
{
excelList[i] = string.Empty;
}
no outer loop necessary

You've written a huge amount of confusing code that could be considerably more compact.
Through th commnts I was able to understand that you have a list of N strings, where N could be between 1 and 13, and you want to turn it into an array of 13 strings with all your list items at the start, and empty strings at the end
So a list of:
"a", "b", "c"
Becomes an array of:
"a", "b", "c", "", "", "", "", "", "", "", "", "", ""
If you want a one liner to generate you a list of 13 strings, from a List x of up to 13 strings:
string[] arrayOf13 = x.AddRange(Enumerable.Repeat("", 13 - x.Count)).ToArray();
If your list x will have an unknown number more than 13:
string[] arrayOf13 = x.AddRange(Enumerable.Repeat("", 13)).Take(13).ToArray();
Or without LINQ using either a for or a while loop:
for(; x.Count < 13; x.Add(""))
string[] arrayOf13 = x.ToArray();
while(x.Count < 13)
x.Add(""));
string[] arrayOf13 = x.ToArray();
If you're willing to have the strings be null rather than empty, you can just declare an array of size 13 (all null) and then use Array.CopyTo():
string[] arrayOf13 = new string[13];
x.ToArray().CopyTo(arrayOf13, 0);

It seems your goal is to get an array of 13 strings (excelList), where each element is eigher string.Empty by default or the corresponding (same index) element from some source list (excList).
So a short-code solution would be to first create a 13-element array, initialized with 'string.Empty' and then copy the source lists elements over, limited to max 13 elements:
var excelList = Enumerable.Repeat(string.Empty, 13).ToArray();
excList.CopyTo(0, excelList, 0, Math.Min(13, excList.Count));

Related

How to remove an element of List<int[]> in C#

I'm trying to program a Sudoku solver in C# in which I'm using a List of an integer array with all the positions of empty fields, because I need them in my algorithm.
In the progress of solving the Sudoku I need to remove those positions which got filled with a number. But somehow my list with empty positions does not get smaller, when I use the Remove-method.
I will explain my problem with a simplified example:
List<int[]> test1 = new List<int[]>();
test1.Add(new int[] { 0, 0 });
test1.Add(new int[] { 1, 7 });
test1.Remove(new int[] { 1, 7 });
The first line generates the list with my one dimensional integer array (which always consists of two values - one for the column and one for the row-number). The empty positions get added in a method, but in this example I just added them in these two lines.
Later on in my algorithm, I want to remove elements by using the Remove-function similarly to the Add-function. It throws no errors, even while compiling. However, it's not removing anything.
I tried using the RemoveAll-method, although I don't really understand, how it works and therefore didn't find a correct solution for my problem.
By trying out a List of integers (not an integer array) the Remove-method works perfectly, but in the case of an array it doesn't seem to work this way.
Even creating a seperat variable rem
int[] rem = new int[] { 1, 7 };
test1.Remove(rem);
does not work.
I'm a beginner so I don't really know if a List of arrays is the best solution in my case.
bool IntArrayPredicate(int[] element)
{
return element.SequenceEqual(new int[] { 2, 3 });
}
List<int[]> listOfIntArray = new List<int[]>();
listOfIntArray.Add(new int[] { 0, 0 });
listOfIntArray.Add(new int[] { 1, 7 });
listOfIntArray.Add(new int[] { 2, 3 });
listOfIntArray.RemoveAll(element => element.SequenceEqual(new int[] { 1, 7 })); //It Works!. Using lambda expresion. Remove by Comparing sequences that match equals.
int[] toRemove = listOfIntArray[0];
listOfIntArray.Remove(toRemove); //It works!. Remove element by exact reference.
listOfIntArray.Remove(new int[] { 2, 3 }); // Not working / References are different.
listOfIntArray.RemoveAll(IntArrayPredicate); // It works!. Same as using lambda but using method reference.
Console.WriteLine($"{nameof(listOfIntArray)} has {listOfIntArray.Count()} elements"); // Yup. 0 elements.
The reason you're not able to remove items from your list using the Remove method is that you're storing reference types in the List, but creating new references when trying to remove an item. Because reference types by default use a reference comparison (not a comparison of their fields) to determine equality, you won't be able to remove items in that way.
One way to resolve this is to create a reference to each object in the List<int[]> outside of the list creation itself. This way, you can use the existing reference as an argument to the Remove method, and, because it's referring to the same object that was added to the list, it will match and be removed:
// Here we have 'item1' and 'item2' that refer to the location of different int[]
int[] item1 = new int[] { 0, 0 };
int[] item2 = new int[] { 1, 7 };
// And now we use those references to add the int[] items to our list
List<int[]> test1 = new List<int[]>();
test1.Add(item1);
test1.Add(item2);
// Finally, we can remove an item using the same reference that we used to add it
test1.Remove(item2);
This is very clunky, however, since we now need to maintain an individual reference for every item in our list as well as the list itself.
Another way to resolve this would be to search for the item we want to remove using our own equality algorithm (rather than relying on the default equality that Remove uses). We can use FirstOrDefault to search for the first item that has a length of 2 and whose values match those that we want. It will return a reference to the item if it's found, or null if it's not found. We can use IndexOf to get the index of the item (or -1 if it's not found), and then pass that index to the RemoveAt method to remove it:
List<int[]> test1 = new List<int[]>();
test1.Add(new int[] { 0, 0 });
test1.Add(new int[] { 1, 7 });
int indexToRemove = test1.IndexOf(test1.FirstOrDefault(item =>
item.Length == 2 && item[0] == 1 && item[1] == 7));
if (indexToRemove >= 0) test1.RemoveAt(indexToRemove);
As you can see, what you're trying to do isn't super easy. As a suggestion to help you think about the problem in a different way, you might consider using a 2-dimensional array to store the sudoku grid. Normally we store the row in the first dimesion and the column in the second dimension:
int[,] grid = new int[9, 9];
You could potentially create a few of these, one to represent the puzzle solution, one to represent the puzzle shown to the user's (with just their guesses), maybe even one to store user's "notes" (if you allow them to tag a cell with possible values before committing to a guess), though that would likely need to be a string[,] or an int[,][].
Then the typical way to loop through the grid would be something like:
for (int row = 0; row < 9; row++)
{
for (int col = 0; col < 9; col++)
{
// Do something with the cell at 'row' 'col' here
// Set a value for this cell
grid[row, col] = row + col;
// Report the value of a cell
Console.WriteLine($"The value at row {row} and column {col} is {grid[row, col]}");
}
}

add values in string array on runtime c#

i am getting string array on runtime like this
string[] array1 = {"5", "4", "2"};
values in array is added on runtime on the basis of checkbox selection from
screen (Note: i have 7 check boxes on screen )
if i check 3 check boxes then 3 values will be add in array1 but i want to add
zero at the end of the array in remaining 4 positions in array like this :
string[] array1 = {"5", "4", "2","0" ,"0","0" , "0"};
during runtime just to fix all 7 position in array ...what should i do ??
I don't get the usage of your requirement. But you can fill up the array with "0" with the following code:
List<string> list = array1.ToList();
for (int i = array1.Length; i < 7; i++)
{
list.Add("0");
}
array1 = list.ToArray();
You can do the following:
const int paddedSize = 7;
var newArray = array1.Concat(Enumerable.Repeat("0", paddedSize - array1.Length)).ToArray();
But maybe you'll understand it better without using Linq; the type you want to use is List<string> which can be dynamically resized, arrays can't. In order to get a list out of an array, you can use the linq extension:
var resized = array1.ToList();
Or
var resized = new List<string>(array1);
And now you simply add 0s until the total count of items is 7:
while (resized.Count < paddedSize)
resized.Add("0");
And back to an array:
var newArray = resized.ToArray();

Sort two dimensional array with different lengths

Hi fellow programmers,
I am trying to sort a two dimensional array. This array represent a collection of objects which has a property which have a value in the list underneath. So the original list does not have to be saved.
The starting situation is:
var list = new List<string>
{
"10-158-6",
"11-158-6",
"90-158-6",
"20-15438-6",
"10-158-6",
"10-158-6-3434",
"10-1528-6"
};
The result should be
var list = new List<string>
{
"10-158-6",
"10-158-6",
"10-1528-6"
"10-158-6-3434",
"11-158-6",
"20-15438-6",
"90-158-6",
};
It should be first ordered on the first part -> then the second -> etc. etc.
I think it is almost impossible to sort these strings so I converted it to a two-dimensional list. I found different solutions to sort multi dimensional list but none can be used for this problem. Also I do not have a clue where to start...
Anyone has an idea how to write a sorting algorithm that doesn't have unnecessary huge big O?
Thanks in advance!
Jeroen
You can use Sort method; let's implement a general case with arbitrary long numbers:
Code:
var list = new List<string>() {
"10-158-6",
"11-158-6",
"90-158-6",
"20-15438-6",
"10-158-6",
"10-158-6-3434",
"10-1528-6",
"123456789012345678901234567890"
};
list.Sort((left, right) => {
var x = left.Split('-');
var y = right.Split('-');
// Compare numbers:
for (int i = 0; i < Math.Min(x.Length, y.Length); ++i) {
// Longer number is always bigger: "123" > "99"
int r = x[i].Length.CompareTo(y[i].Length);
// If numbers are of the same length, compare lexicographically: "459" < "460"
if (r == 0)
r = string.CompareOrdinal(x[i], y[i]);
if (r != 0)
return r;
}
// finally, the more items the bigger: "123-456-789" > "123-456"
return x.Length.CompareTo(y.Length);
});
// Let's have a look at the list after the sorting
Console.Write(string.Join(Environment.NewLine, list));
Outcome:
10-158-6
10-158-6
10-158-6-3434 // <- please, note that since 158 < 1528
10-1528-6 // <- "10-158-6-3434" is before "10-1528-6"
11-158-6
20-15438-6
90-158-6
123456789012345678901234567890
Those look like Version number. If a change from Dash to Dot are not a big change you can simply use C# Version
var list = new List<string>
{
"10-158-6",
"11-158-6",
"90-158-6",
"20-15438-6",
"10-158-6",
"10-158-6-3434",
"10-1528-6"
};
var versions = list.Select(x => new Version(x.Replace('-','.'))).ToList();
versions.Sort();
LiveDemo

Finding an empty string in an array beginning at a specified index

I want to check if an empty string exists in an array after a specified index.
Suppose I have this array:
string[] values = {"1", "2", "2", "4", "", "", ""};
I want to check if an empty value exists from index 3 (where the value is 4). I want to do this without splitting it inter two different arrays of strings.
More specifically my example using an array named files
string[] files;
I want to check from array index 8 to array index 28 if there are any empty values.
You can do it with LINQ:
files.Skip(index).Any(s => s == string.Empty);
You can just use a for loop. Try this:
for(int i = specifiedIndex; i < array.Length; i++)
{
if(array[i].Equals(""))
return true;
}
return false;
This will return true if any of the values at or after the index are empty. If it reaches the end without finding one, it returns false.
You can adjust this to fit your needs. You don't necessarily have to loop the the end of the array, you can set the end condition to a specified index too, say if you wanted to check for an empty string between indexes 5 and 10 but don't care if there are any before or after that.
Use LINQ:-
string[] Values = { "1", "2", "2", "4", "", "", "" };
int specifiedIndex = 3;
var query1 = Values.Skip(specifiedIndex).Select((v, index) => new { v, index }).Where(x => x.v == String.Empty).Select(z => z.index + specifiedIndex);
foreach (var val in query1)
{
Console.WriteLine(val);
}

C# : How to compare two collections (System.Collection.Generic.List<T>) using Linq/Lambda?

I'm having two collections of String like
List<String> l_lstOne = new List<String> { "100", "1X0", "X11", "XXX" },
l_lstTwo = new List<String> { "000", "110", "100", "000" };
I need to compare the two lists and make the second list like
{ "000", "1X0", "X00", "XXX" }
Note:
Both the list will contain same numbe of elements and the length of each element will be same.
The comparision is like
If an mth element in l_lstOne have an 'X' in nth position, the the nth position of the mth in l_lstTwo should be replaced by 'X'.
Example
l_lstOne l_lstTwo Output
100 000 000
1X0 110 1X0
X11 100 X00
So, to solve this i used nested for loop , here is my source code,
for (int l_nIndex = 0; l_nIndex < l_lstTwo.Count; l_nIndex++)
{
String l_strX = String.Empty;
for (int l_nInnerIndex = 0; l_nInnerIndex < l_lstTwo[l_nInnerIndex].Length; l_nInnerIndex++)
{
l_strX += l_lstOne[l_nIndex][l_nInnerIndex] == 'X' ? 'X' : l_lstTwo[l_nIndex][l_nInnerIndex];
}
l_lstTwo[l_nIndex] = l_strX;
}
This code is working fine, but the thing is, its taking more time to execute, i.e almost 600 milliseconds to process 200000 elements and each of length 16.
And moreover i need a Linq or Lambda method to resolve this. So please help me to do this. Thanks in advance.
LINQ will not help you here; LINQ is not meant to modify collections.
You can make your code substantially faster by building a char[] instead of a string; right now, you're building 3.2 million string objects because of the +=.
Instead, you can write
char[] l_strX = new char[l_lstTwo[l_nInnerIndex].Length];
for (int l_nInnerIndex = 0; l_nInnerIndex < l_lstTwo[l_nInnerIndex].Length; l_nInnerIndex++)
{
l_strX[l_nInnerIndex] = l_lstOne[l_nIndex][l_nInnerIndex] == 'X' ? 'X' : l_lstTwo[l_nIndex][l_nInnerIndex];
}
l_lstTwo[l_nIndex] = new string(l_strX);
You could do it with the following statement in .NET 3.5
IEnumerable <String> result =
Enumerable.Range(0, l_lstOne.Count)
.Select(i => Enumerable.Range(0, l_lstOne[i].Length)
.Aggregate(string.Empty, (innerResult, x) => innerResult += l_lstOne[i][x] == 'X' ? 'X' : l_lstTwo[i][x]));
Mh, if I understand it correctly the words in l_lstOne act as a mask for the words in l_lstTwo where the mask is transparent unless it's an X. How about this:
l_lstOne.Zip(l_lstTwo,
(w1, w2) => new String(w1.Zip(w2, (c1, c2) => c1 == 'X' ? c1 : c2).ToArray())))
Zip is a Linq extension method available from .NET 4 on which combines the elements of two lists like a zip. The outer zip basically creates the word pairs to iterate over and the second one creates a the mask (take all characters from the second word unless word one has an X in that position).
Also note that this creates a new sequence of strings rather than replacing the ones in l_lstTwo - that's the Linq way of doing things.

Categories

Resources