I have one arraylist which contains values from a different database, but it stores some duplicate values so, I want to remove duplicate values and store only unique value in Array List.
How can this be done?
Let's try another method. Instead removing duplicates, avoid adding any duplicates. This might be more efficient in your environment.
Here's a sample code:
ArrayList<String> myList = new ArrayList<string>();
foreach (string aString in myList)
{
if (!myList.Contains( aString ))
{
myList.Add(aString);
}
}
You can replace your ArrayList with a HashSet. From the documentation:
The HashSet<T> class provides high performance set operations. A set is a collection that contains no duplicate elements, and whose elements are in no particular order.
If it's absolutely necessary to use an ArrayList, you could use some Linq to remove duplicates with the Distinct command.
var distinctItems = arrayList.Distinct()
you can using This code when work with an ArrayList
ArrayList arrayList;
//Add some Members :)
arrayList.Add("ali");
arrayList.Add("hadi");
arrayList.Add("ali");
//Remove duplicates from array
for (int i = 0; i < arrayList.Count; i++)
{
for (int j = i + 1; j < arrayList.Count ; j++)
if (arrayList[i].ToString() == arrayList[j].ToString())
arrayList.Remove(arrayList[j]);
}
If you can, you should use a HashSet, or any other set class. It is much more efficient for this kind of operation. The main default of the HashSet is that the ordering of the element is not guaranteed to remain the same as your original list (wich may or may not be a problem, depending on your specifications).
Otherwise, if you need to keep the ordering, but only need the duplicates removed when you enumerate through your values, you can use the Distinct method from linq. Just be careful and don't run this query and copy the result everytime you modify your arraylist as it risks impacting your performances.
Hashtable ht = new Hashtable();
foreach (string item in originalArray){
//set a key in the hashtable for our arraylist value - leaving the hashtable value empty
ht[item] = null;
}
//now grab the keys from that hashtable into another arraylist
ArrayList distincArray = new ArrayList(ht.Keys);
If you must use ArrayList, use the Sort method.
Here's a good link # Sort Method of ArrayList.
After the list is sorted, then use an algorithm to iterate/compare all your elements and remove the duplicates.
Have fun,
Tommy Kwee
Related
For now, the best I could think of is:
bool oneMoreTime = true;
while (oneMoreTime)
{
ItemType toDelete=null;
oneMoreTime=false;
foreach (ItemType item in collection)
{
if (ShouldBeDeleted(item))
{
toDelete=item;
break;
}
}
if (toDelete!=null)
{
collection.Remove(toDelete);
oneMoreTime=true;
}
}
I know that I have at least one extra variable here, but I included it to improve the readability of the algorithm.
The "RemoveAll" method is best.
Another common technique is:
var itemsToBeDeleted = collection.Where(i=>ShouldBeDeleted(i)).ToList();
foreach(var itemToBeDeleted in itemsToBeDeleted)
collection.Remove(itemToBeDeleted);
Another common technique is to use a "for" loop, but make sure you go backwards:
for (int i = collection.Count - 1; i >= 0; --i)
if (ShouldBeDeleted(collection[i]))
collection.RemoveAt(i);
Another common technique is to add the items that are not being removed to a new collection:
var newCollection = new List<whatever>();
foreach(var item in collection.Where(i=>!ShouldBeDeleted(i))
newCollection.Add(item);
And now you have two collections. A technique I particularly like if you want to end up with two collections is to use immutable data structures. With an immutable data structure, "removing" an item does not change the data structure; it gives you back a new data structure (that re-uses bits from the old one, if possible) that does not have the item you removed. With immutable data structures you are not modifying the thing you're iterating over, so there's no problem:
var newCollection = oldCollection;
foreach(var item in oldCollection.Where(i=>ShouldBeDeleted(i))
newCollection = newCollection.Remove(item);
or
var newCollection = ImmutableCollection<whatever>.Empty;
foreach(var item in oldCollection.Where(i=>!ShouldBeDeleted(i))
newCollection = newCollection.Add(item);
And when you're done, you have two collections. The new one has the items removed, the old one is the same as it ever was.
Just as I finished typing I remembered that there is lambda-way to do it.
collection.RemoveAll(i=>ShouldBeDeleted(i));
Better way?
A forward variation on the backward for loop:
for (int i = 0; i < collection.Count; )
if (ShouldBeDeleted(collection[i]))
collection.RemoveAt(i)
else
i++;
You cannot delete from a collection inside a foreach loop (unless it is a very special collection having a special enumerator). The BCL collections will throw exceptions if the collection is modified while it is being enumerated.
You could use a for loop to delete individual elements and adjust the index accordingly. However, doing that can be error prone. Depending on the implementation of the underlying collection it may also be expensive to delete individual elements. For instance deleting the first element of a List<T> will copy all the remaning elements in the list.
The best solution is often to create a new collection based on the old:
var newCollection = collection.Where(item => !ShouldBeDeleted(item)).ToList();
Use ToList() or ToArray() to create the new collection or initialize your specific collection type from the IEnumerable returned by the Where() clause.
The lambda way is good. You could also use a regular for loop, you can iterate lists that a for loop uses within the loop itself, unlike a foreach loop.
for (int i = collection.Count-1; i >= 0; i--)
{
if(ShouldBeDeleted(collection[i])
collection.RemoveAt(i);
}
I am assuming that collection is an arraylist here, the code might be a bit different if you are using a different data structure.
My C# program generates random strings from a given pattern. These strings are stored in a list. As no duplicates are allowed I'm doing it like this:
List<string> myList = new List<string>();
for (int i = 0; i < total; i++) {
string random_string = GetRandomString(pattern);
if (!myList.Contains(random_string)) myList.Add(random_string);
}
As you can imagine this works fine for several hundreds of entries. But I'm facing the situation to generate several million strings. And with each added string checking for duplicates gets slower and slower.
Are there any faster ways to avoid duplicates?
Use a data structure that can much more efficiently determine if an item exists, namely a HashSet. It can determine if an item is in the set in constant time, regardless of the number of items in the set.
If you really need the items in a List instead, or you need the items in the resulting list to be in the order they were generated, then you can store the data in both a list and a hashset; adding the item to both collections if it doesn't currently exist in the HashSet.
The easiest way is to use this:
myList = myList.Distinct().ToList();
Although this would require creating the list once, then creating a new list. A better way might be to make your generator ahead of time:
public IEnumerable<string> GetRandomStrings(int total, string pattern)
{
for (int i = 0; i < total; i++)
{
yield return GetRandomString(pattern);
}
}
...
myList = GetRandomStrings(total, pattern).Distinct().ToList();
Of course, if you don't need to access items by index, you could probably improve efficiency even more by dropping the ToList and just using an IEnumerable.
Don't use List<>. Use Dictionary<> or HashSet<> instead!
You could use a HashSet<string> if order is not important:
HashSet<string> myHashSet = new HashSet<string>();
for (int i = 0; i < total; i++)
{
string random_string = GetRandomString(pattern);
myHashSet.Add(random_string);
}
The HashSet class provides high-performance set operations. A set is a collection that contains no duplicate elements, and whose elements are in no particular order.
MSDN
Or if the order is important, I'd recommend using a SortedSet (.net 4.5 only)
not a good way but kind of quick fix,
take a bool to check if in whole list there is any duplicate entry.
bool containsKey;
string newKey;
public void addKey(string newKey){
foreach(string key in MyKeys){
if(key == newKey){
containsKey = true;
}
}
if(!containsKey){
MyKeys.add(newKey);
}else{
containsKey = false;
}
}
A Hashtable would be a faster way to check if an item exists than a list.
Have you tried:
myList = myList.Distinct()
I'm trying to make a function with list.
It is to sort and delete duplicates.
It sorts good, but don't delete duplictates.
What's the problem?
void sort_del(List<double> slist){
//here i sort slist
//get sorted with duplicates
List<double> rlist = new List<double>();
int new_i=0;
rlist.Add(slist[0]);
for (i = 0; i < size; i++)
{
if (slist[i] != rlist[new_i])
{
rlist.Add(slist[i]);
new_i++;
}
}
slist = new List<double>(rlist);
//here get without duplicates
}
It does not work because slist is passed by value. Assigning rlist to it has no effect on the caller's end. Your algorithm for detecting duplicates seems fine. If you do not want to use a more elegant LINQ way suggested in the other answer, change the method to return your list:
List<double> sort_del(List<double> slist){
// Do your stuff
return rlist;
}
with double you can just use Distinct()
slist = new List<double>(rlist.Distinct());
or maybe:
slist.Distinct().Sort();
You're not modifying the underlying list. You're trying to add to a new collection, and you're not checking if the new one contains one of the old ones correctly.
If you're required to do this for homework (which seems likely, as there are data structures and easy ways to do this with LINQ that others have pointed out), you should break the sort piece and the removal of duplication into two separate methods. The methods that removes duplicates should accept a list as a parameter (as this one does), and return the new list instance without duplicates.
i have a list contains set of strings, i want to fetch the data present in the list based on index, with out using iterator.. is there any functions like get() or getat() some sort of method using which we can fetch?
myList[index] is the way to go
List<string> myList = new List<string>();
myList.Add("string 1");
myList.Add("String 2");
Console.WriteLine(myList[0]); // string 1
Console.WriteLine(myList[1]); // String 2
List<string> myList = new List<string();
//add some elements to the list
//then get the third element
string thirdElement = myList[2];
You can just do:
item = list[i];
Use the overloaded index operator.
List<String> list; // ... initialize, populate list
String element = list[1]; // get the element at index 1
If your collection implements IList<T>, just use indexer. Otherwise, if your collection only allows forward-only access (that is, only implements IEnumerable<T>) you can use ElementAt() method, but it still uses iterator under the hood.
I don't know what kind of list you're talking about exactly, but most collections in .net have a CopyTo function, and you can access individual items with the [] operator.
List<string> list = new List<string>();
list.Add("lots of strings");
//If you want to print all the strings you can do:
foreach(string str in list)
Console.WriteLine(str);
//If you want to modify each string in the list, make each lower case for example,
// you can do. this is working by using the index of the elements in the list:
for(int i = 0; i < list.Count; i++)
list[i] = list[i].ToLower();
If you use the generic type List (or another implementation of IList) you can use the index operator to directly access items at certain positions: item = myList[3]
If you use a type that only implements IEnumerable you should use the ElementAt() function.
What's your reason to avoid the use of iterators?
I have a loop that iterates through elements in a list. I am required to remove elements from this list within the loop based on certain conditions. When I try to do this in C#, I get an exception. apparently, it is not allowed to remove elements from the list which is being iterated through. The problem was observed with a foreach loop. Is there any standard way to get around this problem?
Note : One solution I could think of is to create a copy of the list solely for iteration purpose and to remove elements from the original list within the loop. I am looking for a better way of dealing with this.
When using List<T> the ToArray() method helps in this scenario vastly:
List<MyClass> items = new List<MyClass>();
foreach (MyClass item in items.ToArray())
{
if (/* condition */) items.Remove(item);
}
The alternative is to use a for loop instead of a foreach, but then you have to decrement the index variable whenever you remove an element i.e.
List<MyClass> items = new List<MyClass>();
for (int i = 0; i < items.Count; i++)
{
if (/* condition */)
{
items.RemoveAt(i);
i--;
}
}
If your list is an actual List<T> then you can use the built-in RemoveAll method to delete items based on a predicate:
int numberOfItemsRemoved = yourList.RemoveAll(x => ShouldThisItemBeDeleted(x));
You could use LINQ to replace the initial list by a new list by filtering out items:
IEnumerable<Foo> initialList = FetchList();
initialList = initialList.Where(x => SomeFilteringConditionOnElement(x));
// Now initialList will be filtered according to the condition
// The filtered elements will be subject to garbage collection
This way you don't have to worry about loops.
You can use integer indexing to remove items:
List<int> xs = new List<int> { 1, 2, 3, 4 };
for (int i = 0; i < xs.Count; ++i)
{
// Remove even numbers.
if (xs[i] % 2 == 0)
{
xs.RemoveAt(i);
--i;
}
}
This can be weird to read and tough to maintain, though, especially if the logic in the loop gets any more complex.
Another trick is to loop through the list backwards.. removing an item won't affect any of the items you are going to encounter in the rest of the loop.
I'm not recommending this or anything else though. Everything you need this for can probably be done using LINQ statements to filter the list on your requirements.
You can iterate with foreach this way:
List<Customer> custList = Customer.Populate();
foreach (var cust in custList.ToList())
{
custList.Remove(cust);
}
Note: ToList on the list of variables, this iterates through the list created by the ToList but removes the items from the original list.
Hope this helps.
The recommended solution is to put all your elements you want to remove in a separate list and after the first loop, put a second loop where you iterate over the remove-list and remove those elements form the first list.
The reason you get an error is because you're using a foreach loop. If you think about how a foreach loop works this makes sense. The foreach loop calls the GetEnumerator method on the List. If you where to change the number of elements in the List, the Enumerator the foreach loop holds wouldn't have the correct number of elements. If you removed an element a null exception error would be thrown, and if you added an element the loop would miss an item.
If you like Linq and Lamda expressions I would recommend Darin Dimitrov solution, otherwise I would use the solution provided by Chris Schmich.