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 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))
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
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!=\"\"")
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.
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();
}