Selecting keys of a TreeMap by their index - scala

Imagine you have the following TreeMap:
var dates = new TreeMap[Long, Tuple2[Int, Double]]()
I know I can loop through it with:
dates.foreach { case (date, (id, rotation)) =>
...
}
But in my code, this loop takes place within another loop and I would therefore like to advance myself in the dates keys, typically with a currIndex : Int variable that I would increment according to a condition.
I thought one could do something like:
date = dates.keys(currIndex)
but it doesn't look like this is possible... any idea how to do that?

Edit: trying to address your comment:
You can convert the whole keys to an IndexedSeq beforehand:
val keysSeq = dates.keySet.toIndexedSeq
// later, obtain an index
val index: Int = /* ... */
// lookup the key
val (valueInt, valueDouble) = dates(keysSeq(index))
Previous answer
You could try something like this:
dates.iterator.zipWithIndex.foreach {
case ((key, (valueInt, valueDouble)), index) =>
}
Would that work for you? I'm not sure I properly understand your requirement of “increment[ing currIndex] according to a condition”…

Related

use a for loop to add element in to the java.util.ArrayList,but the list's address of the reference always changing

I have a strange problem when I use a for loop to add element in to the java.util.ArrayList , but the list's address of the reference always changing
Here is the code:
var curntRow: Row = null
var startTime: lang.Long = null
//this is the list
var standTime: util.ArrayList[Row] = new util.ArrayList[Row]()
for (row <- usersCoorOrderByTime) {
if (curntRow == null) {
startTime = row.getAs[lang.Long](2)
} else if (!row.getAs[String](1).equals(curntRow.getAs[String](1))) {
//And I use the method list.add() right here
standTime.add(Row(row.getAs[String](0), row.getAs[String](1), row.getAs[DoubleType](4), row.getAs[DoubleType](5), curntRow.getAs[lang.Long](2) - startTime))
startTime = row.getAs[lang.Long](2)
}
curntRow = row
}
And please see the pic that I debug below:
addr is "7703"
Before get in the loop The list's addr is "7703"
When is get in the loop ,the address changes
change to "11268"
change to "11287"
The most strange things is when it end the loop, the address has changed back to where it was originally declared
change back to "7703"
finally I get an empty ArrayList
I found the error
the parameter of for loop is Dataframe, I should turn to Array or List then make for loop
Try using Mutable ArrayBuffer. Below is a simple example. I hope it helps.
val x = scala.collection.mutable.ArrayBuffer[String]()
x += "2"
x += "4"
println(x)

SLICK: To insert value in 3 different tables using one slick api call

The question is related to slick:
I have three tables:
1) Users
2)Team2members
3)Team2Owners
In my post request to users, I am passing values of memberOf and managerOf, these values will be inserted in the tables Team2members and Team2Owners respectively and not in Users table. Though other values of the post request will be inserted in 'Users' table.
My Post request looks like below:
{"kind": "via#user",
"userReference":{"userId":"priya16"},
"user":"preferredNameSpecialChar#domain1.com","memberOf":{"teamReference":{"organizationId":"airtel","teamId":"supportteam"}},
"managerOf":{"teamReference":{"organizationId":"airtel","teamId":"supportteam"}},
"firstName":"Special_fn1",
"lastName":"specialChar_ln1",
"preferredName":[{"locale":"employee1","value":"##$%^&*(Z0FH"}],
"description":" preferredNameSpecialChar test "}
I am forming the query which is shown below:
The query seems to work fine when only memberInsert is defined, when I try to define both the values i.e.memberInsert and managerInsert then insertion happens only for second value.
val query = config.api.customerTableDBIO(apiRequest.parameters.organizationId).flatMap { tables =>
val userInsert = tables.Users returning tables.Users += empRow
val memberInsert = inputObject.memberOf.map(m => m.copy(teamReference = m.teamReference.copy(organizationId = apiRequest.parameters.organizationId))).map { r =>
for {
team2MemberRow <- tables.Team2members returning tables.Team2members += Teams2MembersEntity.fromEmtToTeams2Members(r, empRow.id)
team <- tables.Teams.filter(_.id === r.teamReference.teamId.toLowerCase).map(_.friendlyName).result.headOption
} yield (team2MemberRow, team)
}
val managerInsert = inputObject.managerOf.map(m => m.copy(teamReference = m.teamReference.copy(organizationId = apiRequest.parameters.organizationId))).map { r =>
for {
team2OwnerRow <- tables.Team2owners returning tables.Team2owners += Teams2OwnersEntity.fromEmtToTeam2owners(r, empRow.id)
team <- tables.Teams.filter(_.id === r.teamReference.teamId.toLowerCase).map(_.friendlyName).result.headOption
} yield (team2OwnerRow, team)
}
userInsert.flatMap { userRow =>
val user = UserEntity.fromDbEntity(userRow)
if (memberInsert.isDefined) memberInsert.get
.map(r => user.copy(memberOf = Some(Teams2MembersEntity.fromEmtToMemberRef(r._1, r._2.map(TeamEntity.toApiFriendlyName).getOrElse(List.empty)))))
else DBIO.successful(user)
if (managerInsert.isDefined) managerInsert.get
.map(r => user.copy(managerOf = Some(Teams2OwnersEntity.fromEmtToManagerRef(r._1, r._2.map(TeamEntity.toApiFriendlyName).getOrElse(List.empty)))))
else DBIO.successful(user)
}
}
The query seems to work fine when only memberInsert is defined, when I try to define both the values i.e.memberInsert and managerInsert then insertion happens only for second value.
The problem looks to be with the final call to flatMap.
That should return a DBIO[T]. However, your expression generates a DBIO[T] in various branches, but only one value will be returned from flatMap. That would explain why you don't see all the actions being run.
Instead, what you could do is assign each step to a value and sequence them. There are lots of ways you could do that, such as using DBIO.seq or andThen.
Here's a sketch of one approach that might work for you....
val maybeInsertMemeber: Option[DBIO[User]] =
member.map( your code for constructing an action here )
val maybeInsertManager Option[DBIO[User]] =
manager.map( your code for constructing an action here )
DBIO.sequenceOption(maybeInsertMember) andThen
DBIO.sequenceOption(maybeInsertManager) andThen
DBIO.successful(user)
The result of that expression is a DBIO[User] which combines three queries together.

Sort/Order an Undetermined Number of Columns (LINQ\Entity Framework)

Need to sort/order a list of data based on an undetermined number of columns (1 or more).
What i'm trying to do is loop through the desired columns and add an OrderBy or ThenBy based on their number to the query'd list, but i'm unsuccessful...
Done this, but it doesn't compile:
var query = GetAllItems(); //returns a IQueriable list of items
//for each selected column
for (int i = 0; i < param.Columns.Length; i++)
{
if (i == 0)
{
query = query.OrderBy(x => x.GetType().GetProperty(param.Columns[i].Name));
}
else
{
//ERROR: IQueriable does not contain a definition for "ThenBy" and no extension method "ThenBy"...
query = query.ThenBy(x => x.GetType().GetProperty(param.Columns[i].Data));
}
}
How can i resolve this issue? Or any alternative to accomplish this requirement?
SOLUTION: #Dave-Kidder's solution is well thought and resolves the compile errors i had. Just one problem, OrderBy only executes (actually sorts the results) after a ToList() cast. This is an issue because i can't convert a ToList back to an IOrderedQueryable.
So, after some research i came across a solution that resolve all my issues.
Microsoft assembly for the .Net 4.0 Dynamic language functionality: https://github.com/kahanu/System.Linq.Dynamic
using System.Linq.Dynamic; //need to install this package
Updated Code:
var query = GetAllItems(); //returns a IQueriable list of items
List<string> orderByColumnList = new List<string>(); //list of columns to sort
for (int i = 0; i < param.Columns.Length; i++)
{
string column = param.Columns[i].Name;
string direction = param.Columns[i].Dir;
//ex.: "columnA ASC"
string orderByColumn = column + " " + direction;
//add column to list
orderByColumnList.Add(orderBy);
}
//convert list to comma delimited string
string orderBy = String.Join(",", orderByColumnList.ToArray());
//sort by all columns, yay! :-D
query.OrderBy(orderBy).ToList();
The problem is that ThenBy is not defined on IQueryable, but on the IOrderedQueryable interface (which is what IQueryable.OrderBy returns). So you need to define a new variable for the IOrderedQueryable in order to do subsequent ThenBy calls. I changed the original code a bit to use System.Data.DataTable (to get a similar structure to your "param" object). The code also assumes that there is at least one column in the DataTable.
// using System.Data.DataTable to provide similar object structure as OP
DataTable param = new DataTable();
IQueryable<DataTable> query = new List<DataTable>().AsQueryable();
// OrderBy returns IOrderedQueryable<TSource>, which is the interface that defines
// "ThenBy" so we need to assign it to a different variable if we wish to make subsequent
// calls to ThenBy
var orderedQuery = query.OrderBy(x => x.GetType().GetProperty(param.Columns[0].ColumnName));
//for each other selected column
for (int i = 1; i < param.Columns.Count; i++)
{
orderedQuery = orderedQuery.ThenBy(x => x.GetType().GetProperty(param.Columns[i].ColumnName));
}
you should write ThenBy after OrderBy like this:
query = query
.OrderBy(t=> // your condition)
.ThenBy(t=> // next condition);

CoffeeScript: one liner to map object into another

I have data in the following format:
data = {
car1: {
starting_position: 1,
...
},
car5: {
starting_position: 2,
...
}
}
I want to create an object where starting_position becomes the key and the key in the original data becomes the value. I can do it like this:
byStartingPosition = {}
for k, properties of data
byStartingPosition[properties.starting_position] = k
But I can't imagine there is no one liner to do the same...
If you are using lodash 4.1.0 or later you could do it with this function https://lodash.com/docs#invertBy
_.invertBy data, (v) -> v.starting_position
https://jsfiddle.net/7kf9wn71/2/
You cannot reduce it semantically but you can make it more concise
byStartingPosition = {}
byStartingPosition[v.starting_position] = k for k,v of data
Rayon's comment was aaalmost there. You want to use reduce:
byStartPos = Object.keys(data).reduce(((obj, k) -> start = data[k].starting_position; obj[start] = k; obj), {})
Although that's obnoxiously long, not very idiomatic coffeescript, and frankly less readable than your original, it is a one-liner.

scala-arm. Return type

I'm using scala-arm library to automatically release/close resources (for example InputStream).
But the problem is that code below returns ExtractableManagedResource[Int], not just Int as I want.
val result = for(responseStream <- managed(response.getResponseBodyAsStream)) yield {
val localResult: Int = 1
localResult
}
// result is of type ExtractableManagedResource[Int]
Is there any option to return Int and overcome wrapping result to ExtractableManagedResource?
EDIT: I know that I can just declre result variable as var and assign to it from inside the for-comprehension, but I want more scala-idiomatic way, i.e. without using var
this is easier to implement with the monadic approach by using the aquireAndGet feature
managed(response.getResponseBodyAsStream) acquireAndGet {
responseStream =>
val localResult: Int = 1
localResult
}
From the documentation:
result.opt.get
Refer to your own link, under the title "Monadic style", for further details.