4 ms·
Please show me C++ equivalent of sorted([(k.weight, k.name) for k in somelist], reverse=True)
by aub3bhat 9y ago
Please show me C++ equivalent of
sorted([(k.weight, k.name) for k in somelist], reverse=True)
- nickelbox 9y agoYou could implement the following with a decent bit of work (declaring k and reversed to be variables of special, hand-written/macro-generated types with overloaded operator, and operator=). sorted( (k.weight, k.name).for_(k).in(somelist), reverse=true)); You would never be able to get that past code review, however.
- joshuamorton 9y agoSure, but at that point you've just reimplemented python in macros ;) The other thing to note is that sorted([(k.weight, k.name) for k in somelist], reverse=True) is essentially already typechecked: def biggest_ks(ks: K): return sorted([(k.weight, k.name) for k in ks], reverse=True) The above code now has all the same type guarantees as your c++, actually maybe more since the macros you use are going to be...uhhh, mysterious.
- nickelbox 9y agoThe macro would only be used to generate k for convenience. It could be all implemented in straight, macro-less C++98 in O(minutes). My point was just that you can implement almost whatever you want (even without macros, they'll just expand the design space).
- joshuamorton 9y agoI don't see how you could implement the (k.attr).for_(k) part. That's essentially an assignment, a macro could maybe convert it to a lambda, but I don't see how it would be done macro-free.
- Wehrdo 9y agoI'll bite. std::vector<std::pair<float, std::string>> in_order; std::transform(data.begin(), data.end(), std::back_inserter(in_order), [](auto& item) {return std::make_pair(item.weight, item.name);}); std::sort(in_order.begin(), in_order.end(), std::greater<>()); While I won't claim it to be as elegant as Python, it doesn't seem too ugly. Does anybody have an idea about how `auto` could be utilized to avoid the long vector<pair...> type declaration? For the adventurous: https://repl.it/repls/RepentantGentleKudu https://repl.it/repls/RepentantGentleKudu
- jdashg 9y agoTemplates, auto, and type toys can give you some serious build-your-own syntactic sugar: https://repl.it/repls/PleasingLovingQueenslandheeler https://repl.it/repls/PleasingLovingQueenslandheeler Pulling things out of tuples isn't great, though.
- deathanatos 9y agoNote: my C++ is extremely rusty. Right now, I think that's approximately, vector<tuple<int, string>> output; transform( somelist.begin(), somelist.end(), back_inserter(output), [](const auto &f) { return make_tuple(f.weight, f.name); } ); sort(output.rbegin(), output.rend()); Ranges, I believe, would reduce this a lot, possibly even to a single line. If I am reading the docs on it correctly, something like, vector<auto>(somelist | view::transform([](const auto &f) { return make_tuple(f.weight, f.name); })) | action::sort; I think. Two notes, however: 1. I feel like most of the desire for a static language is to know what type something is. Is C++ exactly as brief as Python? No, as I think you've demonstrated. But I think you're a lot more likely to know the type of something. Rarely do I think I find that Python has annotations, and annotations can be wrong. 2. C++ is, in general, I feel, much more explicit about where copies occur. I elided one of the copies in your example, opting instead for an in-place sort (but this is trivial to fix in the Python).
- mehrdadn 9y ago> vector<auto> Really? O.o How could this possibly work?
- deathanatos 9y agoOh, that was probably a typo (it was late); replace that with a concrete type.
- lmm 9y ago> 1. I feel like most of the desire for a static language is to know what type something is. Is C++ exactly as brief as Python? No, as I think you've demonstrated. But I think you're a lot more likely to know the type of something. Sure, but you don't have to choose between them, there are plenty of languages where you can have both Pythonic terseness and full type safety. E.g. Scala: (for {k <- somelist} yield (k.weight, k.name)).sorted.reverse Many other strongly typed (ML-like) functional languages are similar.
- mehrdadn 9y agoHere (http://rextester.com/QUIK26485 http://rextester.com/QUIK26485): somelist | transformed([](auto &&k) { return make_pair(k.weight, k.name); }) | sorted | reversed;
- tigershark 9y agoNo idea about C++ but in C# seems quite more readable (and flexible) someList.OrderByDescending(x => x.weight).ThenByDescending(x => x.Name); It's quite similar to expressing the concept in English, certainly more than using list comprehension in Python. And how would you order it in Python by ascending on the first field and descending on the second using list comprehension?
- joshuamorton 9y agoThat's not the same thing, you've sorted a list of objects, we're looking for a list of tuples of `weight, name`) In answer to your question though, sorted(((k.weight, k.name) for k in some_list), key=lambda x: (-x[0], x[1]), reverse=True) appears to work. This does use a non-obvious trick, but being more explicit is a smidge difficult, since the key function is called only n times, as opposed to O(nlogn) in the C# example. Alternatively, you can use sorted(sorted(((k.weight, k.name) for k in some_list), key=lambda x: x[1], reverse=True), key=x[0]) Which is more like the original example, and if you're doing it in place, you get outs = [k.weight, k.name) for k in some_list] outs.sort(key=lambda x: x[1], reverse=True) outs.sort(key=lambda x: x[0]) Python's builtin sort is timsort, so despite sorting the list twice, this will still run in approximately NlogN comparisons, not 2NlogN. You could also manually define a custom comparator, ie lambda s, o: (s[0] > o[0] * 10 + s[1] < o[1]) and pass it to `functools.cmp_to_key`.
- Cieplak 9y agoEasy: std::vector<P> people = { P{"jane", 47}, P{"mary", 71}, P{"john", 65} }; ranges::sort(people, [](auto& x, auto& y){ return x.weight > y.weight; }); Compile this gist with `c++ -std=c++1z -I range-v3/include`: https://gist.github.com/cieplak/dcd587c67d989768900e4110e776842c https://gist.github.com/cieplak/dcd587c67d989768900e4110e776...
- joshuamorton 9y agoWhat if two weights are equal, the python code will also sort by name as well ;)