I have two lists.
First list contains values such as letters and numbers.
Length is [0]-[36].
Second list contains similar values and length is also [0]-[36].
I iterate second list twice with specific values to grab an Index key and when I grab Index key from second list, I want to remove items in first list based on Indexes from second one.
Problem is that second iteration doesn't work anymore, because index key has changed in first list.
I should probably convert list to an array (array has fixed index keys, list generates after) but I don't know how to add or remove index key from an array.
I don't use Linq.
Appreciate your help and suggestions
BR
Code sample:
List<int> list_z = new List<int>();
List<int> list_k = new List<int>();
for (int i = 0; i < second_list.Count; i++) {
if (second_list[i] == "K")
{
list_k.Add(i);
}
}
int k = list_k.Count;
for (int i = 0; i < k; i++) {
first_list.RemoveAt(list_k[i]);
}
for (int i = 0; i < second_list.Count; i++)
{
if (second_list[i] == "Z")
{
list_z.Add(i);
}
}
int z = list_z.Count;
for (int i = 0; i < svi_z; i++)
first_list.RemoveAt(lista_z[i]); //here is error, because first_list doesnt have index key number 36 anymore
}
When removing items from a list based on indexes, you should remove them in descending order (e.g. you should remove 11th, 8th, 3d, 2nd items - in this order). In your case:
list_k.Sort();
for (int i = list_k.Count - 1; i >= 0; --i)
first_list.RemoveAt(list_k[i]);
There is a simple solution for removing items from list at a specific index one after the other. That is to order the indexes descending, this way you'll not have any items moved around in the list.
Example:
The Below throws an error:
List<int> list = Enumerable.Range(0, 20).ToList();
List<int> indexesToRemove = new List<int>(){ 5, 13, 18 };
foreach(int i in indexesToRemove)
{
list.RemoveAt(i);
}
While if you do this, you'll get no error:
List<int> list = Enumerable.Range(0, 20).ToList();
List<int> indexesToRemove = new List<int>(){ 5, 13, 18 };
foreach(int i in indexesToRemove.OrderByDescending(x => x))
{
list.RemoveAt(i);
}
So in your case, you just need to call list_z = list_z.OrderByDescending(x => x).ToList(); before the loop and everything should work fine.
Or if you don't want to use linq you can do the following:
list_z.Sort((x, y) => y - x);
for (int i = 0; i < list_z.Count; i++)
first_list.RemoveAt(lista_z[i]);
}
Or you can simplify what your doing:
// Iterate and assign null
for (var i = 0; i < second_list.Count(); i++)
{
if (second_list[i] == "K")
{
first_list[i] = null;
}
}
// Iterate and assign null
for (var i = 0; i < second_list.Count; i++)
{
if (second_list[i] == "Z")
{
first_list[i] = null;
}
}
// remove nulls without linq or lambda
first_list.RemoveAll(delegate (string o) { return o == null; });
Related
I am trying to count how many times a number appears in an array 1 (a1) and then trying to print out that number by storing it in array 2 (a2) just once and then try to print array 2. But first using for loop and a function, I will check that if a number already exist in array 2 then move to next index in array 1, unfortunateley this code is not working; can someone please help me in trying to fix it, I don't need some complex solutions like dictionaries or lists athe moment, although it might be helpful too. thanks, I am not an expert in programming and I try to practise it in my free time, so please help me.
I just want this code to be fixed for my understanding and knowledge
class Program
{
static void Main(string[] args)
{
int i, j;
int[] a1 = new int[10];
int[] a2 = new int[10];
int[] a3 = new int[10];
//takes an input
for (i = 0; i < a1.Length; i++)
{
a1[i] = Convert.ToInt32(Console.ReadLine());
}
for (i = 0; i < a1.Length; i++)
{
Cn(a1, a2); //calls in function
i++; //increments is if true
int count = 0;
for (j = 0; j < a1.Length; j++)
{
//if a number matches with a number in second array
if (a1[i] == a1[j])
{
//do count ++
count++;
// store that number into second array
a2[i] = a1[i];
}
}
//store the number of counts in third array
a3[i] = count;
}
for (i = 0; i < a2.Length; i++)
{
if (a2[i] != 0)
{
Console.WriteLine(a2[i]);
}
}
Console.ReadLine();
}
//function to check if element at current index of array 1 exists in array 2 if yes than break
public static void Cn (int[] aa1, int [] aa2)
{
int k, j;
for ( k = 0; k < aa1.Length; k++)
{
for (j = 0; j < aa2.Length; j++)
{
if (aa1[k] == aa2[j])
break;
}
}
}
}
You probably want to do a group by count:
int[] a1 = new int[10];
var rnd = new Random();
//takes an input
for (int i = 0; i < a1.Length; i++)
{
a1[i] = Convert.ToInt32(rnd.Next(0, 11)); // or Console.ReadLine()
}
var grouped = a1
.GroupBy(x => x)
.Select(g => new
{
Item = g.Key,
Count = g.Count()
}).ToList(); // ToList() is optional, materializes the IEnumerable
foreach (var item in grouped)
{
Console.WriteLine($"number: {item.Item}, count: {item.Count}");
}
This uses a Hash algorithm internally.
You can solve this without a Hash or Dictionary but it wouldn't be very efficient because you need to do lots of linear searches through the arrays.
The advantage of a Hash algorithm is that your lookups or groupings are much faster than if you loop over a complete array to find / increment an item.
I am stuck on a method where I have a List<List<int>> and would like to take each List<int>'s value of each index and add them together.
To be specific:
intList1[0] + intList2[0] + intList3[0]
intList1[1] + intList2[1] + intList3[1]
Although the amount of list and a number of items in each list are not fixed.
The result should then be a List<int> that contains each sum.
You can union all lists together via SelectMany and then group them by initial index with subsequent Sum() calculating:
var answer = lists.SelectMany(x => x.Select((item,index) => new {item,index}).ToList())
.GroupBy(x => x.index).Select(x => x.Sum(y => y.item)).ToList();
Init your result list at the same size as the maximum number of elements in your sublists, and then simply loop into your sublists to sum the different values.
int maximumNumberElements = listContainer.Max(l => l.Count);
List<int> resultList = new List<int>();
for(int i = 0; i < maximumNumberElements; i++)
{
resultList.Add(0);
}
for(int i = 0; i < listContainer.Count; i++)
{
for(int j = 0; j < listContainer[i].Count; j++)
{
resultList[j] += listContainer[i][j];
}
}
I like the dictionary method for these kinds of issues, you could also store some interesting things alongside your value for the dictionary like, the number of items that summed up for that index etc.
// Dictionary of indexes to sums
var sums = new Dictionary<int, int>();
// Iterate your lists.
foreach(var list in lists) {
for (var i = 0; i < list.Count; i++) {
// For the given index, sum up the values in the dictionary.
if (sums.TryGetValue(i, var out value) == false) sums[i] = 0;
sums[i] = sums[i] + list[i];
}
}
Another solution perhaps better in case of larger lists
public static IEnumerable<int> ListSum(IEnumerable<IEnumerable<int>> ll)
{
var resultList = new List<int>();
var enumerators = ll.Select(l => l.GetEnumerator()).ToArray();
bool stillResult;
do
{
stillResult = false;
var sum = 0;
foreach (var e in enumerators)
{
if (e.MoveNext())
{
sum += e.Current;
stillResult = true;
}
}
resultList.Add(sum);
} while (stillResult);
return resultList;
}
I am looking to make it so that the computer tests to find the number of elements in a list, and then saves that as a variable.
int incmount = 0;
List<int> items = new List<int>();
int numofit = Convert.ToInt32(Console.ReadLine());
for (int i = 0; i < numofit; i++)
{
items.Add(incmount);
incmount++;
}
in the example above, I would like to find the number of element in the list "items" and save it as a variable.
The number of elements in the list items can be access via:
items.Count
Like this:
int incmount = 0;
List<int> items = new List<int>();
int numofit = Convert.ToInt32(Console.ReadLine());
for (int i = 0; i < numofit; i++)
{
items.Add(incmount);
incmount++;
}
Console.WriteLine("Number of items: {0}", items.Count);
you can use
items.Count;
but if u need more fun
int count = list.Count(i => i > 10);// get the count of those which is bigger than 10
I Have an array, TempArray[] = {1,3,-1,5,7,-1,4,10,9,-1}
I want to remove every single -1 from this array and copy the remaining arrays into a new array called Original, which should output the numbers as 1,3,5,7,4,10,9
I can only use an if statement within a for loop!
This is what I have so far, but I keep getting an error message, System.IndexOutOfRangeException
for (int i = 0; i < TempArray.Length; i++)
{
if (TempArray[i] != -1)
{
//error occurs at this line
//My attempt is to set the new array, Original[i] equal to TempArray[i] only where the values are not -1.
TempArray[i] = Original[i];
}
}
If you can only use If statement in for loop. This looks like a school project. First you count how many non negative numbers are there in your array. Create new array with that length and fill that array.
int[] TempArray = new int[] {1,3,-1,5,7,-1,4,10,9,-1};
int[] Original ;
int countNonNegative=0;
for (int i = 0; i < TempArray.Length; i++)
{
if (TempArray[i] != -1)
{
countNonNegative++;
}
}
Original = new int[countNonNegative];
int index=0;
for (int i = 0; i < TempArray.Length; i++)
{
if (TempArray[i] != -1)
{
Original[index] = TempArray[i];
index++;
}
}
Console.WriteLine("Original Length = "+Original.Length);
using System.Linq;
int[] withoutNegativeOnes = myArray
.Where(a => a != -1)
.ToArray();
var Original = new int[TempArray.Length];
var originalCounter = 0;
for (int i = 0; i < TempArray.Length; i++)
{
if (TempArray[i] != -1)
{
Original[originalCounter++] = TempArray[i];
}
}
Now Original may contain empty spaces at the end though, but you have all the elements which aren't -1. You can use the following code to iterate through the values:
for (int i = 0; i < originalCounter; i++)
{
Console.WriteLine(Original[i]);
}
and that's because the originalCounter has the last index values that wasn't filled from TempArray's iteration.
try this one
int[] TempArray = { 1, 3, -1, 5, 7, -1, 4, 10, 9, -1 };
int[] original = TempArray.Where(i => i != -1).ToArray();
foreach(int i in original)
Console.WriteLine(i.ToString());
Is there a way to use a loop that takes the first 100 items in a big list, does something with them, then the next 100 etc but when it is nearing the end it automatically shortens the "100" step to the items remaining.
Currently I have to use two if loops:
for (int i = 0; i < listLength; i = i + 100)
{
if (i + 100 < listLength)
{
//Does its thing with a bigList.GetRange(i, 100)
}
else
{
//Does the same thing with bigList.GetRange(i, listLength - i)
}
}
Is there a better way of doing this? If not I will at least make the "thing" a function so the code does not have to be copied twice.
You can make use of LINQ Skip and Take and your code will be cleaner.
for (int i = 0; i < listLength; i=i+100)
{
var items = bigList.Skip(i).Take(100);
// Do something with 100 or remaining items
}
Note: If the items are less than 100 Take would give you the remaining ones.
I didn't like any of the answers listed, so I made my own extension:
public static class IEnumerableExtensions
{
public static IEnumerable<IEnumerable<T>> MakeGroupsOf<T>(this IEnumerable<T> source, int count)
{
var grouping = new List<T>();
foreach (var item in source)
{
grouping.Add(item);
if(grouping.Count == count)
{
yield return grouping;
grouping = new List<T>();
}
}
if (grouping.Count != 0)
{
yield return grouping;
}
}
}
Then you can use it:
foreach(var group in allItems.MakeGroupsOf(100))
{
// Do something
}
You can keep an explicit variable for the end point:
for (int i = 0, j; i < listLength; i = j)
{
j = Math.min(listLength, i + 100);
// do your thing with bigList.GetRange(i, j)
}
In dotnet 6 you can use chunk:
//Child collections will be comprised of 10 elements each.
IEnumerable<int[]> sublists = numbers.Chunk(10);
https://exceptionnotfound.net/bite-size-dotnet-6-chunk-in-linq/
There is also a reference to use a group by to do this, which is quite an interesting solution for older versions of the framework:
Split a collection into `n` parts with LINQ?
List<int> list = null;
int amount_of_hundreds = Math.Floor(list.Count/100);
int remaining_number = list.Count - (amount_of_hundreds * 100);
for(int i = 0; i < amount_of_hundreds; ++i)
{
for(int j = 0; j < 100; ++j)
{
int item = list[(i * 100) + j];
// do what you want with item
}
}
for(int i = 0; i < remaining_number; ++i)
{
int item = list[(amount_of_hundreds * 100) + i];
// do what you want with item
}
you can try below approach also:
int i = 1;
foreach (item x in bigList)
{
batchOperation.Insert(x); //replace it with your action; create the batch
i++;
if (i >100)
{
table.ExecuteBatch(batchOperation); //execute the batch
batchOperation.Clear();
i = 1; // re-initialize
}
}
if (batchOperation.Count >= 1 )
{
table.ExecuteBatch(batchOperation); //do this for the residue items
}
This is my solution, before all, i skip the last rows (rows - skiplast) after i get top of the array.
[TestMethod]
public void SkipTake()
{
var rows = 100;
var skip = 1;
var skiplast = 95;
var result = Enumerable.Range(1, rows).Take(rows - skiplast).Skip(skip - 1 == 0 ? 1 : skip).ToList();
}
You can split one big List to many small lists by limit, like this:
var limit = 100;
foreach (var smallList in bigList.Select((x, i) => new { Index = i, Value = x })
.GroupBy(x => x.Index / limit)
.Select(x => x.Select(v => v.Value).ToList())
.ToList())
{
Console.WriteLine($"{smallList.Count}");
Console.WriteLine(String.Join("\r\n", smallList));
}