Remove all "0" values from List<int> - c#

I'm simply looking for a way to remove all values that == 0 in a List(int).
Thanks.

Here are a few options:
Creating a new list based on the original list and filtering out the 0 values:
var newList = originalList.Where(i => i != 0).ToList();
Modifying the original list:
originalList.RemoveAll(i => i == 0);
The old-school, painful way (for funsies):
for (int i = 0; i < originalList.Length; i++)
{
if (originalList[i] == 0)
{
originalList.RemoveAt(i);
i--;
}
}
The really inefficient, traversing the list repeatedly way (don't do this):
while (originalList.Remove(0)) { }

Related

Iterating through a list is very slow, how to improve the performance

I have a method that iterate through a list and display the result of each type one followed by another meaning that I will display result from rd followed by result from cv followed by adz. But the actual method is very slow and it takes long time to retrieve back the results. what are the ways to improve the performance and will it matter using different data structure
private List<AllJobModel> GetAllJobModelsOrder(List<AllJobModel> result)
{
var countItems = result.Count;
List<AllJobModel> list = new List<AllJobModel>();
while (countItems != 0)
{
for (int i = 0; i < countItems; i++)
{
if (result.ElementAt(i).JobImage.Contains("rd"))
{
list.Add(result.ElementAt(i));
result.RemoveAt(i);
countItems--;
break;
}
}
for (int i = 0; i < countItems; i++)
{
if (result.ElementAt(i).JobImage.Contains("cv"))
{
list.Add(result.ElementAt(i));
result.RemoveAt(i);
countItems--;
break;
}
}
for (int i = 0; i < countItems; i++)
{
if (result.ElementAt(i).JobImage.Contains("adz"))
{
list.Add(result.ElementAt(i));
result.RemoveAt(i);
countItems--;
break;
}
}
for(int i =0; i < countItems; i++)
{
if((!result.ElementAt(i).JobImage.StartsWith("rd") && !result.ElementAt(i).JobImage.StartsWith("adz")) && !result.ElementAt(i).JobImage.StartsWith("cv"))
{
list.Add(result.ElementAt(i));
result.RemoveAt(i);
countItems--;
break;
}
}
}
return list;
}
This is a bad way to sort. You're effectively looping over the list 4 times, extracting specific groups of items each time. You also have a potential bug by removing items as you are iterating over the list. While there are many improvements you can make to your method, a better way would be to use OrderBy with the following sort condition:
list = result.OrderBy( m => m.JobImage.Contains("rd") ? 1 :
m.JobImage.Contains("cv") ? 2 :
m.JobImage.Contains("adz") ? 3 :
4)
.ToList();
Check out this link: https://cc.davelozinski.com/c-sharp/fastest-collection-for-string-lookups
Was very helpfull for me.
Regarding your specific problem. It looks like you're doing some filtering of the data. Linq has an easy way of doing that. I haven't test performance but if you can give me some example data ill try it for you. It could be something like this.
private List<AllJobModel> GetAllJobModelsOrder(List<AllJobModel> result)
{
return result.Where(x => x.JobImage.Contains("rd") || x.JobImage.Contains("cv") || x.JobImage.Contains("adz")).ToList();
}

remove split lines by index with same value from list

-from the list an example is 9120038560640 occurs twice or could be more than that.
-lines stored in List<.string> items = File.ReadAllLines(filepath).ToList();
-every line is split in semi colon.
-second index or [1] should compare to all of the lines and remove with found matched.
363193;9120038560640;7,11;9,99 <---- must be remove
363195;9120038560641;9,81;14,99
363194;9120038560640;9,81;14,99 <--- must be remove
363196;9120038560642;9,81;14,99
363197;9120038560643;9,81;14,99
....
..
.
btw. my file has 25,000++ items.
thank you
okay i got the answer and this is working
items = items.Where(x => x.Split(';')[columnIndex] != "").OrderBy(x => x.Split(';')[columnIndex]).ToList();
List<.string> _items = items.ConvertAll(z => z); //I make independent copy
string[] itemsArr = items.ToArray();
int countA = 0;
foreach (string itemArr in itemsArr)
{
List<int> groupDuplicates = new List<int>();
for (int a = countA; a < itemsArr.Count(); a++)
{
if (itemArr != itemsArr[a])
{
if (itemArr.Split(';')[columnIndex] == itemsArr[a].Split(';')[columnIndex]) //if matched then add
{
groupDuplicates.Add(a); // listing index to be remove
}
else
break; //no way to go through the bottom of the list and also to make the performance faster
}
countA++;
}
if (groupDuplicates.Count() != 0)
{
groupDuplicates.Add(groupDuplicates.First() - 1); //I add here the first item in duplicates
foreach (int m in groupDuplicates)
{
_items.Remove(items.ElementAt(m)); //remove by item not by index
}
}
}

How to remove multiple row from datagridview without using index?

I want to remove multiple row from datagridview,
I tried the below code, here row's are getting deleted based on index.
for (int m = 0; m < dataGridView3.Rows.Count - 1; m++)
{
if (dataGridView3.Rows[m].Cells[2].Value != null)
{
for (int n = 0; n < dataGridView2.Rows.Count - 1; n++)
{
if (dataGridView2.Rows[n].Cells[2].Value != null)
{
if (dataGridView2.Rows[n].Cells[2].Value.Equals(dataGridView3.Rows[m].Cells[2].Value) &&
dataGridView2.Rows[n].Cells[8].Value.Equals(dataGridView3.Rows[m].Cells[8].Value))
{
dataGridView2.Rows.RemoveAt(n);
//break;
}
}
}
}
}
here rows are not getting deleted properly, because index is changed after every single delete, so some records are missing out from loop.
can anyone help me how to solve this?
If you're going to remove items from the collection as you iterate through it like this, you'll need to work backwards through the collection of rows:
// start with the last row, and work towards the first
for (int n = dataGridView2.Rows.Count - 1; n >= 0; n--)
{
if (dataGridView2.Rows[n].Cells[2].Value != null)
{
if (dataGridView2.Rows[n].Cells[2].Value.Equals(dataGridView3.Rows[m].Cells[2].Value) &&
dataGridView2.Rows[n].Cells[8].Value.Equals(dataGridView3.Rows[m].Cells[8].Value))
{
dataGridView2.Rows.RemoveAt(n);
//break;
}
}
}
Alternatively, you could use LINQ to find your matches first, and then remove them:
var rowToMatch = dataGridView3.Rows[m];
var matches =
dataGridView2.Rows.Cast<DataGridViewRow>()
.Where(row => row.Cells[2].Value.Equals(rowToMatch.Cells[2].Value)
&& row.Cells[8].Value.Equals(rowToMatch.Cells[8].Value))
.ToList();
foreach (var match in matches)
dataGridView2.Rows.Remove(match);
Just to make it less of a maintenance head-ache, you might want to use the column name instead of the column index too... just a thought.

How to check if there is an element at the specific index in a list?

How to check if there is an element at the specific index in a list, like
Product[i]
Is it there or not? How to write this check?
If i is the index you want to have, check the Count:
if (i >= 0 && (list.Count - 1) >= i)
{
// okay, the item is there
}
If talking about nullable types, you could also check if the item on that index isn't null:
if (i >= 0 && (list.Count - 1) >= i && list[i] != null)
{
// okay, the item is there, and it has a value
}
try like this
if (Product.Contains(yourItem))
int Index = Array.IndexOf(Product, yourItem);
if you want to check that the index is exist in that particular array then you can just check the length of that array.
if (i < Product.Length && i > -1)
//yes it has
return (Product.Count() -1) <= i;
or if you're feeling hackish:
try { var x = Product[i]; return true; } catch(ArrayIndexOutOfBoundException) { return false; }
or
Product.Skip(i).Any()
or...

Filtering elements of an array

I have an array as
That is, each item has its category in the following index.
I need all the items whose category are TotalNumbers and CurrentNumbers.
I tried
int i = 1;
foreach (string item in statsname)
{
//only number type stats are added to the comboboxes.
if ((statsname[i].ToUpperInvariant()==("TOTALNUMBER")) || ((statsname[i].ToUpperInvariant()==("CURRENTNUMBER"))))
{
comboBox1.Items.Add(statsname[i-1]);
i++;
i++;
}
comboBox1.SelectedIndex = 0;
}
Apparently this does not checks for what I need correctly.
How do I need to modify my codes to get what i need ?
Seems it's better to use a for loop instead of foreach:
for (int i = 1; i < statsname.Length; i += 2)
{
//only number type stats are added to the comboboxes.
if ((statsname[i].ToUpperInvariant()==("TOTALNUMBER")) || ((statsname[i].ToUpperInvariant()==("CURRENTNUMBER"))))
comboBox1.Items.Add(statsname[i-1]);
}
Linq comes to rescue!
var listItems = from s in statsname where s.Equals("TOTALNUMBER", StringComparison.InvariantCultureIgnoreCase) || s.Equals("CURRENTNUMBER", StringComparison.InvariantCultureIgnoreCase) select new ListItem(s);
comboBox1.AddRange(listItems);
Code not tested or compiled, but you can have an idea of what i said.
var filteredValues = Array.FindAll(source, s => s.ToUpperInvariant() == "TOTALNUMBER" ||
s.ToUpperInvariant() == "CURRENTNUMBER").ToList()
I am not sure why you are using index in an foreach loop. The below code should work for you
foreach (string item in statsname)
{
if ( item.ToUpper() == "TOTALNUMBER" || item.ToUpper() == "CURRENTNUMBER")
{
comboBox1.Items.Add(item);
}
}
comboBox1.SelectedIndex = 0;

Categories

Resources