How to sort List<Map<String, String>> - salesforce

I've found a lot of information on how to sort a List, but none on how to sort a List>. Specifically I have a map of key values like:
"Name": "John",
"Savings": 300
I have a list of a bunch of objects like this and need to sort on "Savings". Any ideas?

Have you looked into the Comparable interface? You will need to wrap the Map<String,String> inside a new class that has a comparable() method in order to make it sortable. More info here: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_comparable.htm
public class MapWrapper implements Comparable {
public Map<String,String> record;
public MapWrapper(Map<String,String> record) {
this.record = record;
}
public Integer compareTo(Object compareTo) {
MapWrapper compareToMap = (MapWrapper)compareTo;
if (record.get('Savings') == compareToMap.record.get('Savings')) return 0;
if (record.get('Savings') > compareToMap.record.get('Savings')) return 1;
return -1;
}
}
Your list will contain MapWrapper objects instead of Map<String,String>. You can then sort it using List.sort():
List<MapWrapper> myList = new MapWrapper[]{};
myList.add(new MapWrapper(new Map<String,String>{'Name'=>'John','Savings'=>'300'}));
myList.add(new MapWrapper(new Map<String,String>{'Name'=>'David','Savings'=>'100'}));
System.debug(myList); //Unsorted
myList.sort();
System.debug(myList); //Sorted
If you need to keep your structure as a List<Map<String,String>> without the wrapper, you can still do it but you will need to implement the sort algorithm yourself. The easiest way to do it is using bubble sort.

Related

DynamicData Remove Sort

I am using Reactive DynamicData to sort my collections and update the WPF UI. I can apply a sort easy. The problem is how do I get the items to sort back to their original order? What do I send in the DoSort() so it will return to the unsorted original order?
IObservable<IChangeSet<T>> set;
Subject<IComparer<T>> _sorting;
Subject<Unit> _resorting;
ReadOnlyObservableCollection<T> _itemset;
private SortExpressionComparer<T> _currentSort;
private void DoSort(IComparer<T> sort)
{
_sorting?.OnNext(sort);
//Resort();
}
public void Resort()
{
_resorting?.OnNext(Unit.Default);
}
public ReadOnlyObservableCollection<T> ItemSet()
{
if (_itemset is null)
{
_sorting = new Subject<IComparer<T>>();
_resorting = new Subject<Unit>();
set.Sort(_sorting, resort: _resorting).ObserveOnDispatcher().Bind(out var list).Subscribe();
_itemset = list;
DefaultSort();
}
return _itemset;
}
The IChangeSet<T> that you sort doesn't store the previous ordering of the items somewhere so there is no way to get back the "original" order unless you know how the set was originally sorted and you sort it again using the same IComparer<T>.
What do I send in the DoSort() so it will return to the unsorted original order?
An IComparer<T> that sorts the items in the original order basically.

How to find a specific field from a genetic List object in wpf

I am trying to create a generic class for finding duplicate values for different class.
I am casting each list to an object and passing it as parameter like this
List<StudentModel1> a = new List<StudentModel1>();
List<StudentModel2> b = new List<StudentModel2>();
List<StudentModel3> c = new List<StudentModel3>();
List<object> obj = a.Cast<object>().ToList();//like this
public bool Duplicate(List<object> obj, string Fieldname, string Name)
{
if (obj.Any(x => x.Fieldname.Contains(Name))) { return true; } else { return false; }
}/// something like this;
here i am passing fieldname propery ,string name and object for finding duplicate and return a bool.How to access field name in linq.
please help how to acheive this.
thanks.
If I understand your question correctly, you have 3 different versions of a class: StudentModel1, StudentModel2 and StudentModel3 and you want to be able to compare lists of them. You are casting them to Object so that you can pass any any version of that class to your Duplicate method.
Assuming the above is correct, what you need is inheritance. If that's not something your familiar with you should definitely read up on it.
Consider the following:
class StudentModelBase
{
public string SomeProperty { get; set; }
}
class StudentModel1 : StudentModelBase
{
}
class StudentModel2 : StudentModelBase
{
}
class StudentModel3 : StudentModelBase
{
}
If your Duplicate method should be able to handle any of the "StudentModel" classes, then that means the information needed to tell if there are duplicates must be common to all three versions of that class. The properties and fields which store that information should be moved into StudentModelBase. Then, instead of casting to Object you should cast to StudentModelBase.
Your cast becomes:
List<StudentModelBase> base = a.Cast<StudentModelBase>().ToList();
And your Duplicate method becomes something like the following:
public bool Duplicate(List<StudentModelBase> obj, string Name)
Notice I left out Fieldname because if this is implemented correctly you shouldn't need to pass that as a parameter. You should just be able to access the need members of StudentModelBase like any normal variable, since they should be the same for all versions of "StudentModel".

Why don't array types have Add() method although they implement IList<T>?

Array types such as int[] implement many interfaces, and IList is one of them. IList requires to implement the Add(T) method (because IList inherits from ICollection).
I am writing a "CircularArray" class which contains an array in itself, but doesn't have any index out of range exceptions because of being circular.
The class's definition is this:
public class CircularArray<T> : ICloneable, IList<T>, IStructuralComparable, IStructuralEquatable
It should implement all interfaces Arrays do, so i have to implement The Add method. But... Arrays don't have this method, although they implement the "ICollection" interface.
How is it all done for arrays so that they can implement the ICollection interface and not have Add method? I want to do the same for my CircularArray class.
The explanation is in Daniel's answer in the other topic. To do what you want to achieve is to use explicit interface implementation.
interface ILeft
{
int P { get;}
}
class Middle : ILeft
{
int ILeft.P { get { return 0; } }
}
var mid= new Middle();
var abc = mid.P // invalid;
var abc2 = (mid as ILeft).P; //valid

How to store an array to Firebase via Unity SDK

I am trying to store an Int32[] Array and bool[] Array to Firebase but it isn't working for me. I have searched on various places, but couldn't find a solution. Can anyone tell me, how one can store an array to Firebase Real-time DB from Unity.
I am using System.Reflection to get all the public static fields of the class UserPrefs.
Here is the code, I am trying to do this job...
System.Type type = typeof(UserPrefs);
FieldInfo[] fields = type.GetFields();
foreach (var field in fields) {
if (user != null)
dbReference.Child("users").Child(user.UserId).Child(field.Name).SetValueAsync(field.GetValue(null));
else
Debug.LogError("There is no user LoggedIn to write...");
}
Above code saves all values other than arrays. Error given on arrays is following:
InvalidCastException: Cannot cast from source type to destination
type.
Firebase.Database.Internal.Utilities.Validation.ValidateWritableObject
(System.Object object)
Any help will be much appreciated...
You need a class like this.
public class MyClass
{
public int[] intArray = new int[10];
}
Then you can write that object to the Firebase like this.
public void WriteArrays()
{
MyClass temp = new MyClass();
for (int i = 0; i < temp.intArray.Length; i++)
{
temp.intArray[i] = i;
}
databaseReference.Child("MyArrayNode").SetRawJsonValueAsync(JsonUtility.ToJson(temp));
}
databaseReference is a reference to your root.
Same way you can do this for your bool[] also.
For a more general solution you can copy the JsonHelper class which was suggested here.
Example usage:
string jsonArray = JsonHelper.ToJsonArray(mySerializeableList);
var nodeToUpdate = this.dbReference.Child("wantedNode");
nodeToUpdate.SetRawJsonValueAsync(jsonArray);

How to deserialize several nested Json arrays (more than 2) using DataContractJsonSerializer (Windows Phone 7)

I need to deserialize the next Json string that has several nested Json arrays:
{"d1":[["11791452",[["980",""]]],["11791453",[["1060",""],["1140",""],["1220",""],["1300",""]]],["11791454",[["1070",""]]]]}
I try to do it in several steps, so far I'm able to deserialize three levels of nested arrays. As follow:
{"aOaOa":[[["1060",""],["1140",""],["1220",""],["1300",""]]]}
public class ThreeSimpleNestedArrays
{
public List<List<string[]>> aOaOa; //array of arrays of arrays
public ThreeSimpleNestedArrays()
{
aOaOa = new List<List<string[]>>();
}
}
But the problem arise when I add the extra string in the array structure:
{"TEST": [["11791453",[["1060",""],["1140",""],["1220",""],["1300",""]]],["123456",[["0","1"],["2","3"]]]]}
public class ComplexNestedArray
{
public List<Dictionary<string,List<string[]> >> TEST;
public ComplexNestedArray()
{
TEST = new List<Dictionary<string, List<string[]>>>();
}
}
I'm getting the next error message:
"Unable to cast object of type 'System.String' to type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]'."
What am I missing?
Can anybody suggest a way to deserialize an object like this nested within Json arrays using DataContractJsonSerializer?
The code I use to deserialize is the next:
//Works
DataContractJsonSerializer dcJsonSer = new DataContractJsonSerializer(typeof(ThreeSimpleNestedArrays));
ThreeSimpleNestedArrays root = (ThreeSimpleNestedArrays)dcJsonSer.ReadObject(str);
//Don't work
DataContractJsonSerializer dcJsonSer = new DataContractJsonSerializer(typeof(ComplexNestedArray));
ComplexNestedArray root = (ComplexNestedArray)dcJsonSer.ReadObject(str);
Btw, I'm able to deserilize the object when it is serilized as a Json Object as follow:
{"TEST": [{"s": "11791453","aOa": [["1060",""],["1140",""],["1220",""],["1300",""]]},{"s": "123456","aOa":[["0","1"],["2","3"]]}]}
using a class with two members (a string "s" and a List of string[] "aOa"), but without the names, when the object is serialized as an array, I'm unable to do it.
Any suggestion?
Ok, it looks like the DataContractJsonSerializer is smarter than I though .
It turns out that the way to deserialize that kid of nested objects array is with a class like this:
public class ComplexNestedArray
{
//{"TEST": [["11791453",[["1060",""],["1140",""],["1220",""],["1300",""]]],["123456",[["0","1"],["2","3"]]]]}
public List<List<object>> TEST { get; set; }
}
After that, it is only a mater to do a couple of for cycles and casts to the appropriate class structure.
Btw, This is a MUST in your toolbox in case you have to deal with Json:
json2csharp
Here is my solution. However I'll try to add later a way for your full json:
class Program {
static void Main(string[] args) {
new Program();
}
public Program() {
string full = "{\"d1\":[[\"11791452\",[[\"980\",\"\"]]],[\"11791453\",[[\"1060\",\"\"],[\"1140\",\"\"],[\"1220\",\"\"],[\"1300\",\"\"]]],[\"11791454\",[[\"1070\",\"\"]]]]}";
string simple1 = "{\"aOa\":[[\"1060\",\"\"],[\"1140\",\"\"],[\"1220\",\"\"],[\"1300\",\"\"]]}";
string simple2 = "{\"aOaOa\":[[[\"1060\",\"\"],[\"1140\",\"\"],[\"1220\",\"\"],[\"1300\",\"\"]]]}";
DataContractJsonSerializer d1 = new DataContractJsonSerializer(typeof(S1));
S1 r1 = (S1)d1.ReadObject(new MemoryStream(Encoding.Default.GetBytes(simple1)));
DataContractJsonSerializer d2 = new DataContractJsonSerializer(typeof(S2));
S2 r2 = (S2)d2.ReadObject(new MemoryStream(Encoding.Default.GetBytes(simple2)));
Console.WriteLine("done");
Console.ReadKey();
}
[DataContract]
class S1 {
[DataMember]
List<List<String>> aOa;
}
[DataContract]
class S2 {
[DataMember]
List<List<List<string>>> aOaOa;
}
}

Resources