Sorting dictionary in Swift - swift-playground

I want to know why there is difference in the output?
let cities = ["Shanghai": 450_00_000, "Seoul": 90_00_000]
let new = cities.mapValues { "\($0 / 10_00_000) million people" }
print(new)
// ["Shanghai": "45 million people", "Seoul": "9 million people"]
let cities = ["Shanghai": 45000000, "Seoul": 9000000]
let new = cities.mapValues { "\($0 / 10_00_000) million people" }
print(new)
// ["Seoul": "9 million people", "Shanghai": "45 million people"]

A dictionary is by definition not sorted. There is no guaranteed sorting order. Actually, in recent versions of Swift sorting order is intentionally randomised.
BTW. You really really need to learn how to write a million. One million = 1000000 = 1_000_000. Not 1_00_000. That's one hundred thousand.

Related

Sort shopping list based on previous shopping trips

I want to sort a shopping list based on the order items were checked off in previous shopping trips. For example I go to the store and shop Apples, Bananas and Eggs.
Next I go to the store I shop Avocados and Tomatos and Apples. For my next trip the application sorts Avocados, Tomatos and Apples all before Eggs f.e.
I found this post talking about topological sorting: How to sort a shopping list based on previous pick order?.
However I am not sure how this should work since in theory I could have cycles (A user could theoretically check off apples and then bananas and the next time bananas are checked off before apples).
Could you guide me on how to tackle this problem?
Kind regards
I assume:
Past item orderings should guide ordering the current order.
Any new items appear after any items ordered historically.
Orderings further back in time should have less impact than more recent orderings.
My idea is to assign weights to items seen in past orders based on:
Their position in a historic ordering.
How old that odering is.
The weightings might need adjusting, but, using data from that other question you link to, the Python code below does create orderings based on historic orderings:
from collections import defaultdict
shop = [['Toothpaste', 'Bread', 'Meat', 'Vegetables', 'Milk', 'Ice cream'], # last
['CDs', 'Bread', 'Fruit', 'Vegetables', 'Juice', 'Sugar', 'Chocolates'], # last-but-1
['Meat', 'Juice', 'Milk', 'Sugar']] # last-but-2
def weight_from_index(idx: int) -> float | int:
"Items to the left are of LOwer wt and will sort first."
return idx + 1
def historic_multiplier(idy: int) -> float:
"Older rows have larger multipliers and so are of lower overall weight."
return (idy + 1)**1
def shopping_weights(history: list[list[str]]) -> dict[str, int | float]:
"Weight for items from historic shops."
item2weight = defaultdict(float)
for y, hist in enumerate(history):
for x, item in enumerate(hist):
item2weight[item] += historic_multiplier(y) * weight_from_index(x)
return dict(item2weight)
def order_items(items: list[str], weights) -> list[str]:
wts = weights.copy()
new_items = set(items) - set(wts)
# New items last, but in given order otherwise
max_wt = max(wts.values())
for itm in new_items:
wts[itm] = max_wt + 1 + items.index(itm)
return sorted(items, key = lambda i: wts[i])
item_weights = shopping_weights(shop)
new_shop = ['Curry', 'Vegetables', 'Eggs', 'Milk', 'CDs', 'Meat']
new_order = order_items(new_shop, item_weights)
print(new_order)
# ['CDs', 'Meat', 'Vegetables', 'Milk', 'Curry', 'Eggs']
# Update the historic item orders
shop.insert(0, new_order)

DAX - RANKX Using Two Calculations -

I have a data table that contains transactions by supplier. Each row of data represents one transaction. Each transaction contains a "QTY" column as well as a "Supplier" column.
I need to rank these suppliers by the count of transactions (Count of rows per unique supplier) then by the SUM of the "QTY" for all of each supplier's transactions. This needs to be in 1 rank formula, not two separate rankings. This will help in breaking any ties in my ranking.
I have tried dozens of formulas and approaches and can't seem to get it right.
See below example:
Suppliers ABC and EFG each have 4 transactions so they would effectively tie for Rank 1, however ABC has a Quantity of 30 and EFG has a QTY of 25 so ABC should rank 1 and EFG should rank 2.
Can anyone assist?
https://i.stack.imgur.com/vCsCA.png
Welcome to SO. You can create a new calculated column -
Rank =
var SumTable = SUMMARIZE(tbl, tbl[Supplier], "CountTransactions", COUNT(tbl[Transaction Number]), "SumQuantity", SUM(tbl[Quantity]))
var ThisSupplier = tbl[Supplier]
var ThisTransactions = SUMX(FILTER(SumTable, [Supplier] = ThisSupplier), [CountTransactions])
var ThisQuantity = SUMX(FILTER(SumTable, [Supplier] = ThisSupplier), [SumQuantity])
var ThisRank =
FILTER(SumTable,
[CountTransactions] >= ThisTransactions &&
[SumQuantity] >= ThisQuantity)
return
COUNTROWS(ThisRank)
Here's the final result -
I'm curious to see if anyone posts an alternative solution. In the meantime, give mine a try and let me know if it works as expected.

Best way to sum time in Laravel?

I have a table called transactions with two relevant fields to my question, _start_timestamp_ and _end_timestamp_. I need to sum the amount of time passed between all transactions where _end_timestamp_ is not null. So, the result must be something like Total Time of Transactions: 1 hour and 18 minutes
I've tried using Carbon, but I don't know how to sum all the lines of the table using it.
foreach($timestampStarts as $timestampStart){
$time = new Carbon($timestampStart->start_timestamp);
$shift_end_time =new Carbon($timestampStart->end_timestamp);
dd($time->diffForHumans($shift_end_time));
}
You can use the MySQL TIMESTAMPDIFF function to calculate the difference:
Transaction::whereNotNull('_end_timestamp_')
->sum(DB::raw('TIMESTAMPDIFF(SECOND, _start_timestamp_, _end_timestamp_)'));
This will give you the total in seconds.
You need to retrieve the total difference in minutes. Add the total difference and retrieve the diff for humans. You can retrieve like below:
$diffForHumans = null;
$nowDate = Carbon::now();
$diffInMinutes = 0;
foreach($timestampStarts as $timestampStart){
if(!empty($timestampStart->end_timestamp)){ // if the end timestamp is not empty
$time = new Carbon($timestampStart->start_timestamp);
$shift_end_time =new Carbon($timestampStart->end_timestamp);
//Adding difference in minutes
$diffInMinutes+= $shift_end_time->diffInMinutes($time);
}
}
$totalDiffForHumans = $now->addMinutes($diffInMinutes)->diffForHumans();

How to sort by defined value in mongodb

In my project I'm using SpringBoot 1.4.0-M2 and MongoDb 3.0
I want to implement sorting.
I have collection of documents:
{
"name":"Tim",
"age":19
}
,{
"name":"Jim",
"age":20
}
,{
"name":"Will",
"age":21
}
,{
"name":"Ed",
"age":22
}
I random number from 19 - 22, lets pretend that a number I have got is 21.
Now I want to order by "age" property using my the 21 value.
I want to have order like this 21,22,19,20 so Will,Ed,Tim,Jim
Do You know how to sort in this way?
Best regards!
I don't know of a way to achieve this "wrapping sort" concept in a single query, but you could do it in two queries. The examples below load everything into memory, so you would just need to change things around a bit if you only wanted to operate on one at a time in the case of very large collections.
If you are using the native MongoDB Java driver 3.x:
int age = 21;
DBObject ageSort = new BasicDBObject("age", 1)
List<Document> results = new ArrayList<>();
mongoCollection.find(new BasicDBObject("age", new BasicDBObject("$gte", age)))
.sort(ageSort)
.forEach((Block<Document>) results::add);
mongoCollection.find(new BasicDBObject("age", new BasicDBObject("$lt", age)))
.sort(ageSort)
.forEach((Block<Document>) results::add);
If you are using Spring Data MongoDB:
int age = 21;
Sort ageSort = new Sort(new Sort.Order(Sort.Direction.ASC, "age"))
List<Map> results = mongoTemplate.findAll(
new Query(Criteria.where("age").gte(age)).with(ageSort),
Map.class
);
results.addAll(mongoTemplate.findAll(
new Query(Criteria.where("age").lt(age)).with(ageSort),
Map.class
));

Amazon interview: Timestamp sorting: Find the three page subset sequence repeated maximum number of times [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
The Amazon interview question is:
Given a log file containing (User_Id, URL, Timestamp) user can navigate page from one to the other. Find the three page subset sequence repeated maximum number of times. Records are sorted by Timestamp.
I found this question from this reddit thread.
The poster wrote:
"Given a log file containing (User_Id, URL, Timestamp) user can navigate page from one to the other. Find the three page subset sequence repeated maximum number of times. Records are sorted by Timestamp."
(Although, I wasn't told until late in the interview the file is sorted by timestamp. One of the first things I had asked was if the log was sorted, and my interviewer said no.)
I do think I gave it my all -- I seemed to have been on the right track using a hashmap. I always let my interview know what I was thinking and gave possible outcomes, time complexities, etc.
I am not sure how to approach this problem. What does "Find the three page subset sequence repeated maximum number of times" mean? And if the question didn't say "Records are sorted by Timestamp" (as happened to the poster), then how would that affect the problem?
With "three page subset sequence" I am guessing they mean the three pages must be next to each other, but their internal order does not matter. (A B C = C A B)
public Tuple<string,string,string> GetMostFrequentTriplet(
IEnumerable<LogEntry> entries,
TimeSpan? maxSeparation = null)
{
// Assuming 'entries' is already ordered by timestamp
// Store the last two URLs for each user
var lastTwoUrls = new Dictionary<int,Tuple<string,string,DateTime>>();
// Count the number of occurences of each triplet of URLs
var counters = new Dictionary<Tuple<string,string,string>,int>();
foreach (var entry in entries)
{
Tuple<string,string,DateTime> lastTwo;
if (!lastTwoUrls.TryGetValue(entry.UserId, out lastTwo))
{
// No previous URLs
lastTwoUrls[entry.UserId] = Tuple.Create((string) null, entry.Url, entry.Timestamp);
}
// (comparison with null => false)
else if (entry.Timestamp - lastTwo.Item3 > maxSeparation) {
// Treat a longer separation than maxSeparation as two different sessions.
lastTwoUrls[entry.UserId] = Tuple.Create((string) null, entry.Url, entry.Timestamp);
}
else
{
// One or two previous URLs
if (lastTwo.Item1 != null)
{
// Two previous URLs; Three with this one.
// Sort the three URLs, so that their internal order won't matter
var urls = new List<string> { lastTwo.Item1, lastTwo.Item2, entry.Url };
urls.Sort();
var key = Tuple.Create(urls[0], urls[1], urls[2]);
// Increment count
int count;
counters.TryGetValue(key, out count); // sets to 0 if not found
counters[key] = count + 1;
}
// Shift in the new value, discarding the oldest one.
lastTwoUrls[entry.UserId] = Tuple.Create(lastTwo.Item2, entry.Url, entry.Timestamp);
}
}
Tuple<string,string,string> maxKey = null;
int maxCount = 0;
// Find the key with the maximum count
foreach (var pair in counters)
{
if (maxKey == null || pair.Value > maxCount)
{
maxKey = pair.Key;
maxCount = pair.Value;
}
}
return maxKey;
}
The code goes over the log entries and separates the stream for each user. For each three consecutive URLs for any user, we increment the count for that triplet. Since the order of the three pages are not important, we reorder them in a consistent way, by sorting. In the end, we return the triplet that has the highest count.
Since we only need the last three URLs for each user, we only store the previous two. Combined with the current URL, that makes the triplet we need.
For n URLs, m unique URLs, u users, and s single-visit users, the method will do 2 n - 2 u + s (= O(n)) dictionary lookups, and store up to C(m,3) + u (= O(m3 + u)) tuples.
Edit:
Infer sessions by the duration between requests. If they differ by more than maxSeparation, the new request is treated as the first from that user.

Resources