How to reorder map by nested values - sorting

What is the best way of sorting a map by its nested values in Dart?
Map myMap = {
'A':{'foo':'#', 'pos':2},
'B':{'baa':'#', 'pos':0},
'C':{'yay':'#', 'pos':1},
}
Map mySortedMap = myMap.sort() ???
print(mySortedMap)
Output:
{
'B':{'baa':'#', 'pos':0},
'C':{'yay':'#', 'pos':1},
'A':{'foo':'#', 'pos':2},
}

There is quite simple way: sort keys and create new map from those keys:
Map sortMapByPos(Map map) {
final sortedKeys = map.keys.toList(growable: false)
..sort((k1, k2) => ((map[k1]['pos'] - map[k2]['pos'])));
return Map.fromIterable(sortedKeys, key: (k) => k, value: (k) => map[k]);
}
Usage as below:
print(sortMapByPos(myMap));

Related

The method forEach(Consumer<? super Map<String,Object>>) in the type Iterable<Map<String,Object>> is not applicable for the arguments ((<no type> k

Using Java 8 and getting the below error. I have a List<Map<String, Object>>, Map<String, Object> contains ACC_NO and true or ACC_NO and false.
Have the Map like this:
[{14125=false}, {1210=false}, {13118=false}, {10607=false}, {4973=false}, {12175=false}..............,
Multiple markers at this line
- Lambda expression's signature does not match the signature of the functional interface method accept(Map)
- The method forEach(Consumer>) in the type Iterable> is not applicable for the arguments (( k,
v) -> {})
I need to simply create another map out of it to used
// If value is false, I need to add that again
List<Map<String, Object>> excludeAccounts = new ArrayList<>();
detailsOfPans.forEach((k, v) -> {
System.out.println("Item : " + k + " Count : " + v);
Map<String, Object> myMap = new HashMap<>();
if(!v) {
excludePANs.add(myMap.put(k, v));
}
});
You are currently only iterating over the outer list instead of the maps which form the items of the list. To solve this, you would use
detailsOfPans.forEach(map -> map.forEach((k, v) -> {
// Do something with k, v
}));

For loop optimisation with Java8

How do achieve this with one line ?
I am currently trying to do this
Example :
{{"id" :"2", values: ["10","11", "12"]} , {"id" : "3", values : ["23"]}}
to
{{"id" :"2","value": "10"},{"id": "2","value":"11"},
{"id" :"3","value":"23"} , {"id" : "2", "value":"12"}}
My java code is
Map<Integer, List<Integer>> attrMap = new HashMap<>();
//getAllData() & item.getValues() both returns List
getAllData().forEach(item - > {
item.getValues().forEach(val - > {
attrMap.computeIfAbsent(item.getId(), (k) - >
new ArrayList < > ()).add(val.getValue());
});
});
How can i do it only 1 line ?
Since the IDs are unique, you can do it like
Map<Integer, List<Integer>> attrMap = getAllData().stream()
.collect(Collectors.toMap(
item -> item.getId(),
item -> item.getValues().stream().map(i->i.getValue()).collect(Collectors.toList())));
But, of course, this will still have the performance characteristics of two nested loops. It would support parallel processing, though, but I doubt that your data will be large enough to draw a benefit from parallel processing.
Further, note that the resulting map still structurally matches your first pattern,
{{"id" :"2", values: ["10","11", "12"]} , {"id" : "3", values : ["23"]}}
you just converted item to an entry of the result Map and val to an element of a List<Integer>.
Assuming you have your input like this:
static class Data {
private final int id;
private final List<Integer> values;
public int getId() {
return id;
}
public List<Integer> getValues() {
return values;
}
public Data(int id, List<Integer> values) {
super();
this.id = id;
this.values = values;
}
}
It could be done via:
List<SimpleEntry<Integer, Integer>> result = Arrays.asList(
new Data(2, Arrays.asList(10, 11, 12)),
new Data(3, Arrays.asList(23)))
.stream()
.flatMap(d -> d.getValues().stream().map(x -> new AbstractMap.SimpleEntry<>(d.getId(), x)))
.collect(Collectors.toList());
System.out.println(result); // [2=10, 2=11, 2=12, 3=23]
I am collecting those to Pair or AbstractMap.SimpleEntry.

Rxjs/Typescript: Trying to filter a stream on array intersection

Have a stream, wherein the object contains and array of string. I have a filter which is another array of string. The filter should only emit those items where the intersection of the array is not empty.
This is the psuedo code of what I want to do.
genreFilter: string["poetry", "fiction"]
this.books$ = this.bookInventoryService.getBooks()
.filter(book => {
for( let genre of genreFilter) {
if (book.genres.contains(genre) {
return true;
}
}
});
Is there a way to do array intersection?
Not really an Rx question, but if you are compiling to ES6 you can create a Set from the filter and then use the Array#some to determine if there are any intersections.
const genreFilter: Set<string> = new Set(["poetry", "fiction"]);
this.books$ = this.bookInventoryService.getBooks()
.filter(book => book.genres.some(genre => genreFilter.has(genre)));
If Set is not available you can still do it with an Array if the comparison set is small. Or if the set is large you could create an object out of the filter so you get O(1) lookup:
const genreFilter = ["poetry", "fiction"]
.reduce((obj, key) => {
obj[key] = true
return obj;
}, {});
this.books$ = this.bookInventoryService.getBooks()
.filter(book => book.genres.some(genre => genreFilter[genre]));

Dictionary does not have a member named filter - but it should, shouldn't it?

I'm trying to get code from github for auto-completion to work, but am stuck with an error on line 6 (data.filter) that Dictionary does not have a member named filter. But everything I read in the documentation suggests dictionaries should have a filter method. I've tried every possible combination of unwrapping, self, etc, but the compiler then registers these changes as the error.
Obviously something is going on that I do not understand - any guidance is appreciated.
var data = Dictionary<String, AnyObject>()
func applyFilterWithSearchQuery(filter : String) -> Dictionary<String, AnyObject>
{
var lower = (filter as NSString).lowercaseString
if (data.count > 0) {
var filteredData = data.filter ({
if let match : AnyObject = $0["DisplayText"]{
return (match as NSString).lowercaseString.hasPrefix((filter as NSString).lowercaseString)
}
else{
return false
}
})
}
return filteredData
}
Never heard of dictionary filters - where have you read about that? Arrays do have a filter method, but not dictionaries. What you can do is filter keys or values (accessible via the respective dictionary properties).
You can implement a custom filter on a dictionary with the following code:
var filtered = dict.keys.filter { $0.hasPrefix("t") }.map { (key: $0, value: dict[$0]) }
var newDict = [String : AnyObject]()
for element in filtered {
newDict[element.key] = element.value
}
which filter keys, then maps each key to a (key, value) tuple, then add each tuple to a new dictionary.
Note that to filter keys I used hasPrefix("t") - replace that with something more appropriate to your case
var data = Dictionary<String, AnyObject>()
func applyFilterWithSearchQuery(filter: String) -> [String : AnyObject] {
var lower = filter.lowercaseString
var filteredData = [String : AnyObject]()
if (!data.isEmpty) {
Swift.filter(data) {
(key, value) -> Bool in
if key == "DisplayText" {
filteredData[key] = (value as? String)?.lowercaseString.hasPrefix(lower)
}
return false
}
/* use map function works too
map(data) {
(key, value) -> Void in
if key == "DisplayText" {
filteredData[key] = (value as? String)?.lowercaseString.hasPrefix(lower)
}
}
*/
}
return filteredData
}

Swift: How to declare a 2d array (grid or matrix) in Swift to allow random insert

I need to be able to store information about cells in a 2d matrix or grid. Data is not contiguous so I may need to store data at 5,5 when there is no data at lower rows and columns.
My first thought was an array of arrays dynamically sized. But Swift arrays have bounds that do not grow automatically. If I attempt to place something at index 5 and thats beyond its current size it fails with out of bounds exception.
Is there a collection class in Swift or Cocoa which supports random access to a grid. NSArray doesn't support it either.
Another thought was to store the elements in a dictionary and use a tuple of row, column as the key. However, tuples are not hashable and can't be used as the key to a dictionary.
My current approach is to preinitialize the array with a set size filled with nulls.
Is there a better way?
Here is a very basic implementation, using Dictionary as backend storage:
struct Matrix2D<KeyElem:Hashable, Value> {
var _storage:[KeyElem:[KeyElem:Value]] = [:]
subscript(x:KeyElem, y:KeyElem) -> Value? {
get {
return _storage[x]?[y]
}
set(val) {
if _storage[x] == nil {
_storage[x] = [:]
}
_storage[x]![y] = val
}
}
}
var matrix = Matrix2D<Int, String>()
matrix[1,2] = "foo"
as DictionaryLiteralConvertible:
extension Matrix2D:DictionaryLiteralConvertible {
typealias Key = (x:KeyElem, y:KeyElem)
init(dictionaryLiteral elements: (Key, Value)...) {
for (key, val) in elements {
self[key.x, key.y] = val
}
}
}
var matrix:Matrix2D = [(1,2):"foo", (2,3):"bar"]
Array backend version
struct Matrix2D<T> {
var _storage:[[T?]] = []
subscript(x:Int, y:Int) -> T? {
get {
if _storage.count <= x {
return nil
}
if _storage[x].count <= y {
return nil
}
return _storage[x][y]
}
set(val) {
if _storage.count <= x {
let cols = [[T?]](count: x - _storage.count + 1, repeatedValue: [])
_storage.extend(cols)
}
if _storage[x].count <= y {
let rows = [T?](count: y - _storage[x].count + 1, repeatedValue: nil)
_storage[x].extend(rows)
}
_storage[x][y] = val
}
}
}

Resources