C# List - Group By - Without Linq - c#

I have an object:
IObject
{
string Account,
decimal Amount
}
How do I group by Account and Sum the Amount, returning a List without Linq.
2.0 Framework ... that is why no Linq.
Here is what I have:
ListofObjects = List<IObject>;
foreach (var object in objects)
{
var objectToAdd = new Object(object);
var oa = ListofObjects.Find(x => x.Account == objectToAdd.Account);
if (oa == null)
{
ListofObjects.Add(objectToAdd);
}
else
{
ListofObjects.Remove(oa);
oa.Amount = objectToAdd.Amount;
ListofObjects.Add(oa);
}
}

Easiest answer: use LINQBridge and get all your LINQ to Objects goodness against .NET 2.0... works best if you can use C# 3 (i.e. VS2008 but targeting .NET 2.0).
If you really can't do that, you'll basically need to keep a dictionary from a key to a list of values. Iterate through the sequence, and check whether it already contains a list - if not, add one. Then add to whatever list you've found (whether new or old).
If you need to return the groups in key order, you'll need to also keep a list of keys in the order in which you found them. Frankly it's a pain... just get LINQBridge instead :)
(Seriously, each individual bit of LINQ is actually fairly easy to write - but it's also quite easy to make off-by-one errors, or end up forgetting to optimize something like Count() in the case where it's actually an ICollection<T>... There's no need to reinvent the wheel here.)
EDIT: I was about to write some code, but then I noticed that you want a list returned... a list of what? A List<IList<IObject>>? Or are you actually trying to group and sum in one go? If so, don't you want a list of pairs of key and amount? Or are you going to reuse the same class that you've already got for a single account, but as the aggregate? If it's the latter, here's some sample code:
public static IList<IObject> SumAccounts(IEnumerable<IObject> data)
{
List<IObject> ret = new List<IObject>();
Dictionary<string, IObject> map = new Dictionary<string, IObject>();
foreach (var item in data)
{
IObject existing;
if (!map.TryGetValue(item.Account, out existing))
{
existing = new IObject(item.Account, 0m);
map[item.Account] = existing;
ret.Add(existing);
}
existing.Amount += item.Amount;
}
return ret;
}
Admittedly the extra efficiency here due to using a Dictionary for lookups will be pointless unless you've got really quite a lot of accounts...
EDIT: If you've got a small number of accounts as per your comment, you could use:
public static IList<IObject> SumAccounts(IEnumerable<IObject> data)
{
List<IObject> ret = new List<IObject>();
foreach (var item in data)
{
IObject existing = ret.Find(x => x.Account == item.Account);
if (existing == null)
{
existing = new IObject(item.Account, 0m);
ret.Add(existing);
}
existing.Amount += item.Amount;
}
return ret;
}

Use a dictionary to hold the results. Locating an item in a dictionary is close to an O(1) operation, so it's a lot faster than searching for items in a list.
Dictionary<string, decimal> sum = new Dictionary<string, decimal>();
foreach (IObject obj in objects) {
if (sum.ContainsKey(obj.Account)) {
sum[obj.Account].Amount += obj.Amount;
} else {
sum.Add(obj.Account, obj.Amount);
}
}

Related

How to read Dictionary from FireBase Database in Unity

public void AddDatabase(User user)
{
//User user = new User("pç", 2);
Dictionary<string, object> result = new Dictionary<string, object>();
result["score"] = user.score;
result["username"] = user.username;
reference.Child("datas").Child(user.username).SetValueAsync(result);
}
public void GetDatabase()
{
FirebaseDatabase.DefaultInstance.GetReference("datas").GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
// Handle the error...
}
else if (task.IsCompleted)
{
DataSnapshot snapshot = task.Result;
ArrayList childs = new ArrayList();
//Dictionary<string, object> xyz = new Dictionary<string, object>();
foreach (var item in snapshot.Children)
{
childs.Add(item.Value);
//xyz.Add("dat", item.Value);
}
// this does not work I can't see values and keys in the console
foreach (KeyValuePair<string, object> item in childs)
{
Debug.Log(item.Key);
Debug.Log(item.Value);
}
}
});
}
I write datas into firebase with AddDatabase and I want to read every Score and Username one by one in order with GetDatabase so I can put them Leaderboard but I can't how can I do that and I already checked firebase database docs.
Thank you
Depending on the data returned in GetValueAsync, DataSnapshot may have a Dictionary<string, object> in it already:
public void GetDatabase()
{
FirebaseDatabase.DefaultInstance.GetReference("datas").GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
// Handle the error...
}
else if (task.IsCompleted)
{
DataSnapshot snapshot = task.Result;
var dictionary = snapshot.Value as Dictionary<string, object>;
if (dictionary != null) {
// dictionary stuff here
}
}
});
}
From the docs:
Value returns the data contained in this snapshot as native types. The possible types returned are:
bool
string
long
double
IDictionary{string, object}
List{object} This list is recursive; the possible types for object in the above list is given by the same list. These types correspond to the types available in JSON.
Now a quick note: the Unity SDK does guess at whether the Value should be a List or a Dictionary if it has children. The general rule is:
It's a List if the elements are sequential and roughly 50% of the keys in the range are filled (ex: 0="hi", 1="I'm", 3="a", 4="list" is a list even though it's missing 2). Otherwise it will try to make a Dictionary. If you are dealing with integer keys, you may want to have mirrored logic for dealing with a List or Dictionary just to be safe.
What is the type of snapshot.Children and what is the type of its contents? If the contents is not of type KeyValuePair<string, object> then the second foreach loop won't work properly (I am not familiar enough with non-generic collections to say what would actually happen).
I strongly recommend using types from the System.Collections.Generic namespace, such as List<T>, rather than non-generic collections like ArrayList. This will make it easier to see what your code is doing. In addition to being easier to work with, they also have better performance because they don't require casting.
Try to follow the two examples:
How to use Firebase Database in Unity (REST API)
Retrieving Data

Uppercase all keys in a series of C# KeyValuePairs

I have a list of JSON objects, each of which I'm iterating over and I simply want to process all of the KeyValuePairs therein so that the keys are uppercased, then return the revised objects.
This is what I attempted:
public static List<JObject> normalizeKeys(List<JObject> jObjList)
{
jObjList.ForEach(jobj => {
foreach(var kvp in jobj)
{
kvp.Key = kvp.Key.ToUpper();
}
});
return jObjList;
}
but it doesn't execute and instead I get KeyValuePair<string, JToken>.Key cannot be assigned to -- it is readonly. Does anyone have any suggestions for how to accomplish what I'm after?
Though the given answer works, I would be inclined to say that it is both not as elegant as it could be, and not as generally useful as it could be. We can make it more of both. To begin with, solve the problem for one object:
public static JObject NormalizeKeys(JObject originalObject)
{
var newObject = new JObject();
foreach (var kvp in originalObject)
newObject.Add(kvp.Key.ToUpper(), kvp.Value);
return newObject;
}
And now to solve the problem for a list:
var newList = oldList.Select(x=>NormalizeKeys(x)).ToList();
Or, even shorter:
var newList = oldList.Select(NormalizeKeys).ToList();
Isn't that much more pleasant than all that nested loop stuff? Say how to normalize one object, and then say that you want to apply that function to the list, and you're done.
Guess you know the answer yourself, you must create a new collection and copy the items over, since key is key, it's case sensitive, and cannot be changed, as otherwise you might end up with probably 2 sets of data, one set with normal case, and the other with upper cases.
The solution is as the following:
public static List<JObject> normalizeKeys(List<JObject> jObjList)
{
// create a new list for return and copy over the existing items
var jObjReturnList = new List<JObject>(jObjList.Count);
jObjList.ForEach(jobj =>
{
var jObjNew = new JObject();
foreach (var kvp in jobj)
{
jObjNew.Add(kvp.Key.ToUpper(), kvp.Value);
}
jObjReturnList.Add(jObjNew);
});
return jObjReturnList;
}

A single foreach statement which iterates over two collections

So I have two collections - one of int?, and one of string.
I want to iterate over both, and I have a good chunk of code that I want to perform to each. However there are some slight differences. if the value is an int?, some additional code is needed.
I'm trying to follow DRY principles, so I don't want to rewrite my code. I also don't want to put it in an external function, as this is already abstracted away from my MVC app controller code and I don't want it getting needlessly complex.
Is there a way to do something like this in c#
foreach(object o in (ints && strings))
{
if(o is int)
{
// do in specific stuff
}
// do all my generic stuff.
}
EDIT:
It's actually int? not int. when I try and combine them into a generic list of type List<object> I get an error
With this particular structure, you can combine them into one big object collection using Concat, like:
foreach (object o in ints.Cast<object>().Concat(strings.Cast<object>()))
But I'd probably suggest breaking out your functionality into a method, and running two loops:
foreach (int i in ints) {
DoSomething(i);
DoSomethingWithInt(i);
}
foreach (string s in strings) {
DoSomething(s);
DoSomethingWithString(s);
}
That will keep things clean and a little more readable in my opinion.
I think it would be cleaner to put the generic stuff in a common function, then loop over both collections. That way you get rid of the somewhat odd if int stuff.
foreach(int number in ints)
{
// do int specific stuff
GeneralFunction(number);
}
foreach(string stringValue in strings)
{
GeneralFunction(number);
}
This could also work for you:
IEnumerator en1 = ints.GetEnumerator();
IEnumerator en2 = strings.GetEnumerator();
while((en1.MoveNext()) && (en2.MoveNext()))
{
WhateverActionWithNullableInt((int?)en1.Current);
WhateverActionWithString((string)en2.Current);
}
Yes, you can do this:
List<int> ints = new List<int>();
List<string> strings = new List<string>();
foreach (object o in ints.Cast<object>().Concat(strings))
{
if (o is int)
{
// do in specific stuff
}
// do all my generic stuff.
}
I would separate it into functions and take advantage of overloading myself, but you said you didn't want to do that.
You should create a new list, which is the concatenation of the two lists :
EDIT
List<object> list = new List<object>();
List<int> ints = new List<int>(); ints.Add(74); ints.Add(47);
List<string> strings = new List<string>(); strings.Add("hello"); strings.Add("hello2");
list.AddRange(ints.Cast<object>());
list.AddRange(strings.Cast<object>());
foreach (object o in list)
{
Trace.WriteLine(o);
if (o is int)
{
// do in specific stuff
}
// do all my generic stuff.
}

Retrieving the key of a value from a hash table c#

I have a hash table that contains values of a^j. j is the key and a^j is the value.
I am now calculating another value a^m. I basically want to see if a^m is in the hash table.
I used the ContainsValue fn. to find the value. How would i go about finding out the key of the value?
Here is a little snippet of where i want to implement the search for the value.
Dictionary<BigInteger, BigInteger> b = new Dictionary<BigInteger, BigInteger>();
***add a bunch of BigIntegers into b***
for(int j=0; j < n; j++)
{
z = q* BigInteger.ModPow(temp,j,mod);
***I want to implement to search for z in b here****
}
Does this change anything? the fact that i am searching while inside a for loop?
The fastest way is probably to iterate through the hashtable's DictionaryEntry items to find the value, which in turn gives you the key. I don't see how else to do it.
Firstly, you should absolutely be using Dictionary<TKey, TValue> instead of Hashtable - if you're using BigInteger from .NET 4, there's no reason not to use generic collections everywhere you can. Chances are for the most part you'd see no difference in how it's used - just create it with:
Dictionary<BigInteger, BigInteger> map =
new Dictionary<BigInteger, BigInteger>();
to start with. One thing to watch out for is that the indexer will throw an exception if the key isn't present in the map - use TryGetValue to fetch the value if it exists and a bool to say whether or not it did exist.
As for finding the key by value - there's no way to do that efficiently from a Dictionary. You can search all the entries, which is most easily done with LINQ:
var key = map.Where(pair => pair.Value == value)
.Select(pair => pair.Key)
.First();
but that will iterate over the whole dictionary until it finds a match, so it's an O(n) operation.
If you want to do this efficiently, you should keep two dictionaries - one from a to a^j and one from a^j to a. When you add an entry, add it both ways round. Somewhere on Stack Overflow I've got some sample code of a class which does this for you, but I doubt I'd be able to find it easily. EDIT: There's one which copes with multiple mappings here; the "single mapping" version is in the answer beneath that one.
Anyway, once you've got two dictionaries, one in each direction, it's easy - obviously you'd just lookup a^m as a key in the second dictionary to find the original value which created it.
Note that you'll need to consider whether it's possible for two original keys to end up with the same value - at that point you obviously wouldn't be able to have both mappings in one reverse dictionary (unless it was a Dictionary<BigInteger, List<BigInteger>> or something similar).
Edit: Changed to use Dictionary<TKey, TValue>
Dictionary<TKey, TValue> is an IEnumerable<KeyValuePair<TKey, TValue>>. If you do a foreach over it directly, you can get both the key and value for each entry.
class SomeType
{
public int SomeData = 5;
public override string ToString()
{
return SomeData.ToString();
}
}
// ...
var blah = new Dictionary<string, SomeType>();
blah.Add("test", new SomeType() { SomeData = 6 });
foreach (KeyValuePair<string, SomeType> item in blah)
{
if(e.Value.SomeData == 6)
{
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}
}
If you have a newer version of the .Net framework, you could use Linq to find your matches, and place them in their own collection. Here's a code sample showing a little bit of Linq syntax:
using System;
using System.Collections;
using System.Linq;
class SomeType
{
public int SomeData = 5;
public override string ToString()
{
return SomeData.ToString();
}
}
class Program
{
static void Main(string[] args)
{
var blah = new Dictionary<string, SomeType>();
blah.Add("test", new SomeType() { SomeData = 6 });
// Build an enumeration of just matches:
var entriesThatMatchValue = blah
.Where(e => e.Value.SomeData == 6);
foreach (KeyValuePair<string, SomeType> item in entriesThatMatchValue)
{
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}
// or: ...
// Build a sub-enumeration of just keys from matches:
var keysThatMatchValue = entriesThatMatchValue.Select(e => e.Key);
// Build a list of keys from matches in-line, using method chaining:
List<string> matchingKeys = blah
.Where(e => e.Value.SomeData == 6)
.Select(e => e.Key)
.ToList();
}
}
private object GetKeyByValue(object searchValue)
{
foreach (DictionaryEntry entry in myHashTable)
{
if (entry.Value.Equals(searchValue))
{
return entry.Key;
}
}
return null;
}

What's the fastest way to convert List<string> to List<int> in C# assuming int.Parse will work for every item?

By fastest I mean what is the most performant means of converting each item in List to type int using C# assuming int.Parse will work for every item?
You won't get around iterating over all elements. Using LINQ:
var ints = strings.Select(s => int.Parse(s));
This has the added bonus it will only convert at the time you iterate over it, and only as much elements as you request.
If you really need a list, use the ToList method. However, you have to be aware that the performance bonus mentioned above won't be available then.
If you're really trying to eeke out the last bit of performance you could try doing someting with pointers like this, but personally I'd go with the simple linq implementation that others have mentioned.
unsafe static int ParseUnsafe(string value)
{
int result = 0;
fixed (char* v = value)
{
char* str = v;
while (*str != '\0')
{
result = 10 * result + (*str - 48);
str++;
}
}
return result;
}
var parsed = input.Select(i=>ParseUnsafe(i));//optionally .ToList() if you really need list
There is likely to be very little difference between any of the obvious ways to do this: therefore go for readability (one of the LINQ-style methods posted in other answers).
You may gain some performance for very large lists by initializing the output list to its required capacity, but it's unlikely you'd notice the difference, and readability will suffer:
List<string> input = ..
List<int> output = new List<int>(input.Count);
... Parse in a loop ...
The slight performance gain will come from the fact that the output list won't need to be repeatedly reallocated as it grows.
I don't know what the performance implications are, but there is a List<T>.ConvertAll<TOutput> method for converting the elements in the current List to another type, returning a list containing the converted elements.
List.ConvertAll Method
var myListOfInts = myListString.Select(x => int.Parse(x)).ToList()
Side note: If you call ToList() on ICollection .NET framework automatically preallocates an
List of needed size, so it doesn't have to allocate new space for each new item added to the list.
Unfortunately LINQ Select doesn't return an ICollection (as Joe pointed out in comments).
From ILSpy:
// System.Linq.Enumerable
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
return new List<TSource>(source);
}
// System.Collections.Generic.List<T>
public List(IEnumerable<T> collection)
{
if (collection == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
}
ICollection<T> collection2 = collection as ICollection<T>;
if (collection2 != null)
{
int count = collection2.Count;
this._items = new T[count];
collection2.CopyTo(this._items, 0);
this._size = count;
return;
}
this._size = 0;
this._items = new T[4];
using (IEnumerator<T> enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
this.Add(enumerator.Current);
}
}
}
So, ToList() just calls List constructor and passes in an IEnumerable.
The List constructor is smart enough that if it is an ICollection it uses most efficient way of filling a new instance of List

Categories