Find duplicate values in an arraylist without using LINQ - c#-2.0

I have an arraylist with few duplicate items. I need to know the count of each duplicated item. I am using 2.0 so cannot use linq.
I had posted a similar question earlier, but my question was not clear.
Thanks
Prady

I've done something in the past. My solution was to loop through the ArrayList and store the counts in a dictionary. Then loop though the dictionary to display the results:
ArrayList list = new ArrayList();
list.Add(1);
list.Add("test");
list.Add("test");
list.Add("test");
list.Add(2);
list.Add(3);
list.Add(2);
Dictionary<Object, int> itemCount = new Dictionary<object, int>();
foreach (object o in list)
{
if (itemCount.ContainsKey(o))
itemCount[o]++;
else
itemCount.Add(o, 1);
}
foreach (KeyValuePair<Object, int> item in itemCount)
{
if (item.Value > 1)
Console.WriteLine(item.Key + " count: " + item.Value);
}
Output:
test count: 3
2 count: 2
Edit
Realized I used the var keyword which is not a 2.0 feature. Replaced it with KeyValuePair.

Option 1: Sort the list and then count adjacently Equal items (requires you to override the Equals method for your class)
Option 2: Use your unique identifier (however you're defining two objects to be equal) as the key for a Dictionary and add each of your objects to that entry.

i needed something similar for a project a long time ago, and made a function for it
static Dictionary<object, int> GetDuplicates(ArrayList list, out ArrayList uniqueList)
{
uniqueList = new ArrayList();
Dictionary<object, int> dups = new Dictionary<object, int>();
foreach (object o in list)
{
if (uniqueList.Contains(o))
if (!dups.ContainsKey(o))
dups.Add(o, 2);
else
dups[o]++;
else
uniqueList.Add(o);
}
return dups;
}

Related

Java 8 parallelStream forEach iteration [duplicate]

Java Code Like :
List<Detail> DbDetails = ... Like 50000 rows records
Map<Long, List<Detail>> details = new HashMap();
DbDetails .parallelStream().forEach(detail -> {
Long id = detail.getId();
details.computeIfAbsent(id, v -> new ArrayList<>()).add(detail);
});
Then ...
details.entrySet().stream().forEach(e -> {
e.getValue(); // Some value is empty
});
I guess it because HashMap is thread-unsafe, so I use Hashtable instead of it. Then it run ok, all value has value, but I don't know why?
HashMap is not thread-safe, so don't use parallel streams with it.
Besides, why do that there, when streams can do it for you?
DbDetails.parallelStream().collect(Collectors.groupingBy(Detail::getId))

How do I remove the foreach from this linq code?

I'm fairly new at MVC and linq and viewmodels in particular. I managed to get a create and index views to work. The "insert" wasn't as hard as the "list".
I have this linq query:
public ActionResult Index()
{
List<BlendElVM> BEVM = new List<BlendElVM>();
var list = (from Blend in db.blends
join BlendEl in db.blendEl on Blend.ID equals BlendEl.ID
select new
{
Blend.ID, Blend.Title, Blend.TransDt, BlendEl.Comment
}).ToList();
foreach (var item in list)
{
BlendElVM o = new BlendElVM(); // ViewModel
o.Comment = item.Comment;
o.Title = item.Title;
o.TransDt = item.TransDt;
o.ID = item.ID;
BEVM.Add(o);
}
return View(BEVM);
}
What I'm not sure about is the "foreach" section. When I'm running in debug, the "list" shows up fine, but if I comment out the "foreach" I get an error - ie not expecting the model. What does the foreach do? It has to do with the database, but I don't understand the where it is using the "o" and setting the columns. I thought it would all be in one linq query. Is it possible to combine the two and eliminate the "foreach"?
var BEVM = (from blend in db.blends
join BlendEl in db.blendEl on Blend.ID equals BlendEl.ID
select new BlendELVM
{
ID = blend.ID,
Title = blend.Title,
TransDT = blend.TransDt,
comment = blendEl.Comment
}).ToList();
I believe that the foreach is needed in order to read every element in the object so in this case you have:
BlendElVM o = new BlendElVM();
So you're creating and object named " o " of the type BlendELVM and this object contains all the attributes that you declared before which are: ID, Title, TransDT, etc
When you put:
foreach (var item in list)
{
BlendElVM o = new BlendElVM(); // ViewModel
o.Comment = item.Comment;
o.Title = item.Title;
o.TransDt = item.TransDt;
o.ID = item.ID;
BEVM.Add(o);
}
You're assigning to the new object o the item that you're reading in the list and in the end adding it to the BVEM list and answering if you can combine them i will say no because at first you're declaring the query and then you're reading the items on the list and assining them to the BEVM list

How to apply Where condition on Umbraco Collection

I want to apply where condition on Umbraco Collection.
Code:
var workList = CurrentPage.work.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var workCollection = Umbraco.Content(workList);
#foreach (var item in workCollection.Where("productImage!=\"\"").Skip((i - 1) * iterationCount).Take(iterationCount))
But I always get data without filter.
ProductImage is media picker
If you want to stick to dynamic object, you should try:
var workList = CurrentPage.work.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var workCollection = Umbraco.Content(workList);
#foreach (var item in workCollection.Where("productImage != null && productImage != string.Empty").Skip((i - 1) * iterationCount).Take(iterationCount)) { ... }
Personally, I prefer to deal with strongly typed objects, so another solution may be:
var workList = CurrentPage.work.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var workCollection = Umbraco.TypedContent(workList);
#foreach (IPublishedContent item in workCollection.Where(x => x.HasValue("productImage")).Skip((i - 1) * iterationCount).Take(iterationCount)) { ... }
For more informations check: https://our.umbraco.org/documentation/reference/templating/mvc/querying.
You can also check a package called Umbraco Core Property Value Converters: https://our.umbraco.org/projects/developer-tools/umbraco-core-property-value-converters/ which is automatically converting some data type values into easily accessed objects / lists etc. E.g. media picker value is returned as IPublishedContent model and you can access it's properties directly from the returned value.
So I guess what you want to do is get items from workcollection that have a filled projectImage property?
I personally like to do this with a lambda expression, in your case it would be something like this
workCollection.Where(x => x.HasValue("productImage"))
instead of
workCollection.Where("productImage!=\"\"")

duplicate unsorted linked list

I've found this function to remove duplicate values in linked list:
public static void deleteDups (LinkedListNode n){
Hashtable table = new Hashtable();
LinkedListNode previous = null;
while(n!=null){
if(table.containsKey(n.data)){
previous.next = n.next;
} else {
table.put(n.data, true);
previous = n;
}
n = n.next;
}
}
Why is better copy the element in an hash table and not to another structure like a different linked list?
Thanks
Because checking for the existence of an item is an O(N) operation in a linked-list, however it is O(1) for the hash-table. Performance is the reason.
if(table.containsKey(n.data))
this is where the current item is checked if it is seen before (a duplicate) and that operation would be costly when implemented via a linked-list.

Why does my attempt to trim strings in a List<string> not appear to work?

I tried the following code in LINQPad and got the results given below:
List<string> listFromSplit = new List<string>("a, b".Split(",".ToCharArray())).Dump();
listFromSplit.ForEach(delegate(string s)
{
s.Trim();
});
listFromSplit.Dump();
"a" and " b"
so the letter b didn't get the white-space removed as I was expecting...?
Anyone have any ideas
[NOTE: the .Dump() method is an extension menthod in LINQPad that prints out the contents of any object in a nice intelligently formatted way]
you're just creating a trimmed string, not assigning anything to it.
var s = " asd ";
s.Trim();
won't update s, while..
var s = " asd ";
s = s.Trim();
will..
var listFromSplit = "a, b".Split(',').Select(s=>s.Trim());
would, i suppose, be how i'd go about it.
The String.Trim() method returns a string representing the updated string. It does not update the string object itself, but rather creates a new one.
You could do this:
s = s.Trim();
However you cannot update a collection while enumerating through it so you'd want to either fill a new List while enumerating over the existing one or populate the List manually using the string array returned by String.Split.
Filling a new list:
List<string> temp = new List<string>("a, b".Split(",".ToCharArray()));
List<string> listFromSplit = new List<string>();
temp.ForEach(delegate(string s)
{
listFromSplit.Add(s.Trim());
});
listFromSplit.Dump();
Populating Manually:
string[] temp = "a, b".Split(",".ToCharArray());
List<string> listFromSplit = new List<string>();
foreach (string s in temp)
{
listFromSplit.Add(s.Trim());
};
listFromSplit.Dump();
Further to the answer posted by Adrian Kuhn you could do the following:
var result = listFromSplit.Select(s => s.Trim());
The string instances are immutable. Anything that seems to modify one, creates a new instance instead.
You are not assigning the trimmed result to anything. This is a classic error, I've only just got out of the habit of making this mistake with string.Replace :)
I have no IDE up and running, but this should get the job done (unless I am wrong):
var result = from each in listFromSplit select each.Trim();
Split on both spaces and commas and remove any empty entries. All nice and trimmed. Assumes that your strings don't contain spaces, though.
List<string> listFromSplit =
new List<string>( "a , b ".Split( new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries ));
The linq options others have provided should work well. As another option, here is an extension method using a for loop:
public static void TrimCollection(this IList<string> stringCollection) {
for (int i = 0; i <= stringCollection.Count() - 1; i++)
stringCollection[i] = stringCollection[i].Trim();
}

Resources