How to create LinkedHashMap with equality that manage order - unit-testing

In my unit test, I need to test order of elements as that :
test("Check map order", () {
LinkedHashMap<String, String> actualMap = LinkedHashMap();
actualMap["0"] = "firstValue";
actualMap["1"] = "secondValue";
LinkedHashMap<String, String> expectedMap = LinkedHashMap();
expectedMap["1"] = "secondValue";
expectedMap["0"] = "firstValue";
print("actual: $actualMap");
print("expected: $expectedMap");
expect(actualMap, isNot(expectedMap));
});
This test fails, event if order is respected:
actual: {0: firstValue, 1: secondValue}
expected: {1: secondValue, 0: firstValue}
package:test_api expect
test/services/game/negotiation/NegotiationGameService_test.dart 33:7 main.<fn>.<fn>
Expected: not {'1': 'secondValue', '0': 'firstValue'}
Actual: {'0': 'firstValue', '1': 'secondValue'}

First idea that works but is a bit boring:
test("Check map order", () {
LinkedHashMap<String, String> actualMap = LinkedHashMap();
actualMap["0"] = "firstValue";
actualMap["1"] = "secondValue";
LinkedHashMap<String, String> expectedMapSameOrder = LinkedHashMap();
expectedMap["0"] = "firstValue";
expectedMap["1"] = "secondValue";
LinkedHashMap<String, String> expectedMapDifferentOrder = LinkedHashMap();
expectedMap["1"] = "secondValue";
expectedMap["0"] = "firstValue";
print("actual: $actualMap");
print("expected: $expectedMapSameOrder");
print("expected: $expectedMapDifferentOrder");
expect(actualMap, expectedMapSameOrder);
expect(actualMap.keys, isNot(orderedEquals(expectedMapSameOrder.keys)));
expect(actualMap, expectedMapDifferentOrder);
expect(actualMap.keys, orderedEquals(expectedMapDifferentOrder.keys));
});

Related

Why Int attributes are not being saved in DynamoDB when using AWS SDK 2.x?

I added an Int attribute in my class named isAlsoActor but it doesn't get saved in DynamoDB. Here is the class I'm trying to save in Dynamo:
package me.brunosantana.dto
import com.fasterxml.jackson.annotation.JsonInclude
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbAttribute
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbIgnore
import software.amazon.awssdk.services.dynamodb.model.AttributeValue
private const val TYPE = "ARTIST"
#DynamoDbBean
//#JsonInclude(JsonInclude.Include.NON_EMPTY)
data class Artist(
#get:DynamoDbAttribute("ArtistName")
var name: String,
#get:DynamoDbAttribute("Nationality")
var nationality: String,
#get:DynamoDbAttribute(value = "IsAwardWinner")
var isAwardWinner: Boolean,
#get:DynamoDbAttribute(value = "IsAlsoActor")
var isAlsoActor: Int,
#get:DynamoDbIgnore
val songs: MutableList<Song> = mutableListOf()
): DynamoBaseModel(
pkType = "artist",
pkId = name.lowercase().replace(" ", "_"),
sk = "artist#${name.lowercase().replace(" ", "_")}",
gsi1pk = "type#artist",
gsi1sk = "type#artist",
) {
constructor(
name: String,
nationality: String,
isAwardWinner: Boolean,
isAlsoActor: Int
) :
this(
name = name,
nationality = nationality,
isAwardWinner = isAwardWinner,
isAlsoActor = isAlsoActor,
songs = mutableListOf()
)
#Deprecated(message = "Intended to be used only by AWS SDK")
constructor() :
this(
name = "",
nationality = "",
isAwardWinner = false,
isAlsoActor = 0,
songs = mutableListOf()
)
#DynamoDbAttribute("Type")
fun getType(): String {
return TYPE
}
fun setType(type: String) {
// Do nothing, this setter is just to make the AWS SDK 2.x happy
}
fun addAllSongs(songs: MutableList<Song>){
this.songs.addAll(songs)
}
companion object {
fun attributeMapToArtist(attributeMap: Map<String, AttributeValue>): Artist {
val name = attributeMap["ArtistName"]!!.s()
val nationality = attributeMap["Nationality"]!!.s()
val isAwardWinner = attributeMap["IsAwardWinner"]?.bool() ?: false
val isAlsoActor = attributeMap["IsAlsoActor"]?.n()?.toInt() ?: 0
val versionTimestamp = attributeMap["VersionTimestamp"]?.s()
val artist = Artist(
name = name,
nationality = nationality,
isAwardWinner = isAwardWinner,
isAlsoActor = isAlsoActor)
artist.versionTimestamp = versionTimestamp
return artist
}
}
}
Here is the code responsible for saving it in Dynamo (it's using putItem):
fun saveModel(model: DynamoBaseModel){
val pk = "${model.pkType}#${model.pkId}"
val existingModel = findByPkAndSk(pk, model.sk)
val existingVersion = existingModel?.versionTimestamp
val incomingVersion = model.versionTimestamp!!
try {
when(model){
is Artist -> {
save(model, incomingVersion, existingVersion, true)
}
is Song -> {
save(model, incomingVersion, existingVersion, true)
}
}
}catch (e: DynamoDbException){
e.printStackTrace()
}
}
fun findByPkAndSk(pk: String, sk: String): DynamoBaseModel? {
val tableName = "music"
val pkAttribute = AttributeValue.builder().s(pk).build()
val skAttribute = AttributeValue.builder().s(sk).build()
val queryReq = QueryRequest.builder()
.tableName(tableName)
.consistentRead(false)
.keyConditionExpression("pk = :pk and sk = :sk")
.expressionAttributeValues(mapOf(":pk" to pkAttribute, ":sk" to skAttribute))
.build()
try {
val queryResponse: QueryResponse = client.query(queryReq)
queryResponse.items().firstOrNull {
return when(it["Type"]!!.s()) {
"ARTIST" -> Artist.attributeMapToArtist(it)
"SONG" -> Song.attributeMapToSong(it)
else -> throw Exception("Not found")
}
}
} catch (e: DynamoDbException) {
System.err.println(e.message)
}
return null
}
private final inline fun <reified T> save(model: T, incomingVersion: String, existingVersion: String?, versioningCheck: Boolean){
println("incoming: $incomingVersion existing: $existingVersion")
val musicTable: DynamoDbTable<T> =
enhancedClient.table("music", TableSchema.fromBean(T::class.java))
if(versioningCheck){
if(existingVersion == null){
println("no existing version")
musicTable.putItem(model)
}else{
val incomingDate = DateUtils.convertStringToZonedDateTime(incomingVersion)
val existingDate = DateUtils.convertStringToZonedDateTime(existingVersion)
if(DateUtils.isIncomingDateNewer(incomingDate, existingDate)){
println("override")
musicTable.putItem(model) //check how to override properly
}else{
println("Skip. $incomingVersion is older than $existingVersion")
}
}
}else{
println("check disabled")
musicTable.putItem(model)
}
}
Does anyone have any idea why it's not saving the Int attribute? It saves the item in the table, but the Int attribute does not appear there.
Thank you.

Return list outside ForEach loop return only last item in Kotlin

I need to return all list items, in forEach it works fine, outside the loop it only returns the last item.
fun scanAndConvertFile(): String {
val scanner = Scanner(System.`in`)
print("Enter path to file to convert: ")
val fileName: String = scanner.nextLine()
val bufferedReader: BufferedReader = File(fileName).bufferedReader()
var result = bufferedReader.use { it.readText() }
val header = result.substring(0, result.indexOf(":61:"))
val body = result.substring(result.indexOf(":61:"), result.lastIndexOf(":61:220131C6"))
val footer = result.substring(result.lastIndexOf(":61:220131C6"), result.length)
var list = body.split(":61:")
list = list.filter { it.isNotEmpty() }
list = list.map {
":61:$it"
}
list.forEach() {
val part1 = it.substring(0, it.indexOf("?20"))
var part2ToBePasted = it.substring(it.indexOf("?20"), it.indexOf("?00"))
part2ToBePasted = part2ToBePasted.drop(3)
val part3 = it.substring(it.indexOf("?00"), it.indexOf("?27"))
var part4ToPast = it.substring(it.indexOf("?27"), it.indexOf("?28"))
part4ToPast = part4ToPast.drop(3)
val part5 = it.substring(it.indexOf("?28"), it.length)
list = if(part4ToPast.equals("")) {
listOf(part1.plus("?20").plus(part2ToBePasted).plus(part3).plus("?27").plus(part4ToPast).plus(part5))
} else {
listOf(part1.plus("?20").plus(part4ToPast).plus(part3).plus("?27").plus(part4ToPast).plus(part5))
}
// println(list) - works good
}
val converted = header.plus(list).plus(footer)
// println(converted) - print only last element of list
return converted
}
I tried to clean up your code a little (with no guarantee of course since I do not have any test data):
fun scanAndConvertFile(): String {
print("Enter path to file to convert: ")
val fileName: String = Scanner(System.`in`).nextLine()
val bufferedReader: BufferedReader = File(fileName).bufferedReader()
val result = bufferedReader.use { it.readText() }
val header = result.substring(0, result.indexOf(":61:"))
val footer = result.substring(result.lastIndexOf(":61:220131C6"), result.length)
val list = result
.substring(result.indexOf(":61:"), result.lastIndexOf(":61:220131C6"))
.split(":61:")
.filter { it.isNotEmpty() }
.map { ":61:$it" }
.map {
val indexOf00 = it.indexOf("?00")
val indexOf20 = it.indexOf("?20")
val indexOf27 = it.indexOf("?27")
val indexOf28 = it.indexOf("?28")
val substring27to28 = it.substring(indexOf27, indexOf28).drop(3)
it.substring(0, indexOf20)
.plus("?20")
.plus(if (substring27to28 == "") it.substring(indexOf20, indexOf00).drop(3) else substring27to28)
.plus(it.substring(indexOf00, indexOf27))
.plus("?27")
.plus(substring27to28)
.plus(it.substring(indexOf28, it.length))
}
return header.plus(list).plus(footer)
}
Basically you need to use map instead of forEach to return a list. map is used to transform each element of a list, while with forEach you do something to or with each element, but no list is returned.

Compare two HashMap in Java

How to fetch the HashMap based on Max-key field
Eaxmple:-
List<Map<String, Integer>> data = new ArrayList<Map<String, Integer>>();
Map<String, Integer> map1 = new HashMap<>();
map1.put("A", 10);
map1.put("B", 15);
map1.put("C", 20);
Map<String, Integer> map2 = new HashMap<>();
map2.put("A", 20);
map2.put("B", 30);
map2.put("C", 50);
Map<String, Integer> map3 = new HashMap<>();
map3.put("A", 50);
map3.put("B", 60);
map3.put("C", 70);
data.add(map1);
data.add(map2);
data.add(map3);
Here I have 3 maps that I'm storing in the List.
Now I want to filter a map based on max A key value.
In the above map3 A value has the max integer value.
Expected out is:-
In the last only the map3 should present inside the List.
Is it possible to filter using java8?
Any suggestions would be helpful
I finally able to do this with help of comparator
Here is the code that will filter based filtering based on max date:-
Result is stored in the firstMap variable...
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String args[]) throws ParseException {
Map<String, String> s = test();
System.err.println(s.toString());
}
public static Map<String, String> test() throws ParseException {
List<Map<String, String>> data = new ArrayList<Map<String, String>>();
Map<String, String> map1 = new HashMap<>();
map1.put("A", "2021-03-08");
Map<String, String> map2 = new HashMap<>();
map2.put("A", "2021-03-23");
Map<String, String> map3 = new HashMap<>();
map3.put("A", "2021-03-21");
data.add(map1);
data.add(map2);
data.add(map3);
SimpleDateFormat si = new SimpleDateFormat("yyyy-MM-dd");
Date firstMax = si.parse(data.get(0).get("A"));
Map<String, String> firstMap = data.get(0);
for (Map<String, String> map : data) {
Date loopMax = si.parse(map.get("A"));
if (firstMax.compareTo(loopMax) < 0) {
firstMax = loopMax;
firstMap = map;
}
}
return firstMap;
}
}
Output:-
{A=2021-03-23}

Flutter/Dart how to combine values in list of maps

I have the following list of maps:
[
{
"id":1,
"asset_id":"name1",
"asset_price":100.00,
"asset_date":"09-09-09"
},
{
"id":2,
"asset_id":"name2",
"asset_price":50.00,
"asset_date":"10-09-09"
},
{
"id":3,
"asset_id":"name1",
"asset_price":100.00,
"asset_date":"11-09-09"
}
]
How can I produce a new list that combines duplicate asset_id and sums the price as below:
[
{
"id":1,
"asset_id":"name1",
"asset_price":200.00,
"asset_date":"09-09-09"
},
{
"id":2,
"asset_id":"name2",
"asset_price":50.00,
"asset_date":"10-09-09"
}
]
Class
int id;
String assetId;
String assetName;
String assetSymbol;
String assetImage;
double assetAmount;
String assetCurrency;
double assetPrice;
String assetDate;
Asset(
{this.id,
this.assetId,
this.assetName,
this.assetSymbol,
this.assetImage,
this.assetAmount,
this.assetCurrency,
this.assetPrice,
this.assetDate});
Map<String, dynamic> toMapWithoutId() {
final map = new Map<String, dynamic>();
map["id"] = id;
map["asset_id"] = assetId;
map["asset_name"] = assetName;
map["asset_symbol"] = assetSymbol;
map["asset_image"] = assetImage;
map["asset_amount"] = assetAmount;
map["asset_currency"] = assetCurrency;
map["asset_price"] = assetPrice;
map["asset_date"] = assetDate;
return map;
}
Map<String, dynamic> toMap() {
final map = new Map<String, dynamic>();
map["id"] = id;
map["asset_id"] = assetId;
map["asset_name"] = assetName;
map["asset_symbol"] = assetSymbol;
map["asset_image"] = assetImage;
map["asset_amount"] = assetAmount;
map["asset_currency"] = assetCurrency;
map["asset_price"] = assetPrice;
map["asset_date"] = assetDate;
return map;
}
//to be used when converting the row into object
factory Asset.fromMap(Map<String, dynamic> data) => new Asset(
id: data["id"],
assetId: data["asset_id"],
assetName: data["asset_name"],
assetSymbol: data["asset_symbol"],
assetImage: data["asset_image"],
assetAmount: data["asset_amount"],
assetCurrency: data["asset_currency"],
assetPrice: data["asset_price"],
assetDate: data["asset_date"]);
}

How to edit a list of object c# linq to xml

<Team Side="Home" TeamRef="ref123">
<Goal PlayerRef="p1111" Time="10" >
<Assist PlayerRef="p9999">p9999</Assist>
</Goal>
<Goal PlayerRef="p4444" Time="11" >
<Assist PlayerRef="p9999">p9999</Assist>
</Goal>
<Goal PlayerRef="p7777 Time="13" >
<Assist PlayerRef="p9999">p9999</Assist>
</Goal>
<Goal PlayerRef="p7777 Time="17" >
<Assist PlayerRef="p9999">p9999</Assist>
</Goal>
</Team>
public void GetScorer(string side, string OCompetition, string OSeason, string OGameId)
{
try
{
var xDoc = XDocument.Load(test);
var query = from q in xDoc.Descendants("Team")
where (string)q.Attribute("Side") == side
from d in q.Elements("Goal")
select new
{
TeamRef = q.Attribute("TeamRef").Value,
PlayerRef = d.Attribute("PlayerRef").Value,
Time = d.Attribute("Time").Value
};
var count = 0;
foreach (var qq in query)
{
if (side == "Home")
{
if (HomeSlateScorerList[count].PlayerRef != qq.PlayerRef)
{
HomeSlateScorerList.Add(new Scorer() { PlayerRef = qq.PlayerRef, Time = qq.Time, LastName = GetPlayerNameSlate(qq.PlayerRef, OSeason, OCompetition, OGameId) });
}
else
{
HomeSlateScorerList[count].Time = HomeSlateScorerList[count].Time + "' ";
}
}
if (side == "Away")
{
AwaySlateScorerList.Add(new Scorer() { PlayerRef = qq.PlayerRef, Time = qq.Time, LastName = GetPlayerNameSlate(qq.PlayerRef, OCompetition, OSeason, OGameId) });
}
count++;
}
}
catch (Exception)
{
// ignored
}
}
I would like to edit a player in a list of players
HomeSlateScorerList = new List<Scorer>();
AwaySlateScorerList = new List<Scorer>();
what I would like to achieve is for e.g. there are two players with the ref of "p7777" so in the list of object I would like to have one player with the playerref of "p7777" so if the player exist the format will be
playerref = "p7777"
Time = 13' 17'
or if one player its
Time = 13'
or if another goal is added to the xml its
Time = 13' 17' 25'
HomeSlateScorerList = HomeSlateScorerList
.GroupBy(s => s.PlayerRef)
.Select(g => new Scorer { PlayerRef = g.Key, Time = string.Join(", ", g.Select(v => v.Time)) })
.ToList();
Thanks to: #SergeyS SergeyS