1. 18

    1. 17

      Since Python 3.9 you can merge two dicts with dict1 | dict2

    2. 8

      In K, most of these are are a single built-in operation or simple composition:

      |:                 / reverse a string/list
      ~2!                / is a number even? (works on nested structures, too)
      ?,                 / intersection of two lists
      ?:                 / remove duplicates from a list
      #:                 / string/list length (normal)
      +/~0=              / string/list length (avoid using 'count')
      {&/|/x=/:y}        / does y contain all elements of x?
      10?"a"             / 10 random letters (a special case of 'draw')
      10/                / turn a list of digits into a base-10 number
      {x~|x}             / is a string/list a palindrome?
      ,/                 / flatten a list (one level)
      ,//                / flatten a list (recursively)
      *<#:'=:            / find the most frequent element of a list
      ,                  / a 'list join' is also a dictionary union
      1. 1

        Today I learned about this

        Out of curiosity what’s K

        1. 3

          K is a curious language in the APL family created by Arthur Whitney. One of its primary features is conciseness (which makes it look like line noise), to be able to see as much of an entire program as possible at a time. The latest version I know of is Shakti, also known as k9. Open source implementations I’m aware of include ngn/k, oK, and kona, though they all implement different versions/variations of the language.

      2. 1

        How do you search google for the meaning of these symbols? Google loves to strip out non-alphanumeric.

        1. 1

          There aren’t many symbols to remember; K only uses standard ASCII. An expert will have most or all of the vocabulary memorized in the same sense that most programmers don’t need Google to look up the symbol for performing addition in their language of choice.

          For beginners (or anyone acclimating to an unfamiliar dialect), K interpreters typically include a built-in reference card. More comprehensive reference manuals are available for oK and K2.

    3. 7

      The same, but in Ruby:

      Reverse a String:
      reversed_string = "Hello World".reverse
      Check if a Number is Even:
      is_even = -> { _1.even? }
      Find the Intersection of Two Lists:
      intersection = list1 & list2
      Remove Duplicates from a List:
      no_duplicates = list.uniq
      Calculate the Length of a String without Using .length/.size/.count:
      length = "Hello World".chars.sum { 1 }
      Check if a List Contains All Elements of Another List:
      contains_all = list1.all? { list2.include?(_1) }
      contains_all = (list2 - list1).empty?
      contains_all = (list1 & list2) == list1
      Generate a String of Random Characters:
      random_str = ('a'..'z').to_a.sample(10).join
      Convert a List of Integers to a Single Number:
      num = [1, 2, 3, 4, 5].join
      Palindromic Check:
      is_palindrome = -> { _1 == _1.reverse }
      List Flattening:
      flatten_list = [[[1, 2], [3, 4]], []].flatten
      Find the Most Frequent Element in a List:
      most_frequent = list.tally.max_by {_2}.first
      most_Frequent = list.max_by { list.count(_1) }
      # the second one is probably much slower
      Merge Two hashes:
      merged_hash = hash1.merge(hash2)
      merged_hash = {**hash1, **hash2}
      1. 2

        That’s pretty interesting,

        Ruby has been on my list for a long time and I have been really amazed by the simplicity of Ruby and RoR web framework

        And thanks for sharing this

    4. 9

      I don’t get the point of this article. None of these is a lifesaver, and you learn all of this early on in your learning of the language. This article could make sense as an advocacy piece of a kind “look at these cool things you can do in this language,” but Python is already ubiquitous these days, so it is difficult to imagine someone who would be interested in what Python has to offer but just didn’t happen to notice this tiny obscure language just yet…

      1. 7

        I hope you enjoyed reading this and had the opportunity to learn something new

        I think that sums it up. There’s always something new to learn.

        I’m not a Python developer, so I found the article very interesting, even though (in my very biased opinion), Ruby does it much better.

      2. 5

        I work with data scientists who write Python and they learn little things like this all the time.

        For notes on the article:

        1. Also cool to use reversed(string) when you don’t have an idea of the length, then "".join(reversed_string) later.
        2. Don’t make this a lambda, write a def, Guido’s orders. def is_even(x: int): return x % 2
        3. For sure
        4. Don’t even turn it back to a list! Pass around generators, they are great!
        5. Don’t do this! Using len() is normal and I think the length of a string is stored alongside the string in memory
        6. You can do this like 3, set(a) ^ set(b) should be an empty set. (I think that’s what’s being achieved here.)
        7. Cool!
        8. Cool?
        9. Cool.
        10. Didn’t know this, nice
        11. Sure
        12. As @spookylukey said
      3. 2

        I’ve had a lot of colleagues that would write a for loop for most of those idioms, resulting code both slower and less concise. That said, the list could have used the standard library more, and avoided mistakes such as the quadratic contains_all.

      4. 1

        every day somebody is born who doesn’t know about my_list[::-1]!

        In the abstract, writing out things more clearly is Better(TM). But if you’re really verbose about certain things, then suddenly your function that could have been 4 lines is now 12 lines, or it could have been 10 and is now 25… and at one point length becomes a legibility concern!

        I don’t necessarily “agree” with a all the listed one-liners, but there is value in context to terser code, especially if it’s idiomatic (-> easier to read for other pythonistas). If only because terse code + a comment might be even clearer than a more verbose approach (that might be hiding bugs).

    5. 3

      It may be useful to note that the list flattening is not recursive (unlike the ruby answer), only one level is flattened:

      >>> sum([[[1], 2], [3, 4]], [])
      [[1], 2, 3, 4]

      If you’re okay with cheating and eval, there is a one-liner for recursive flattening:

      >>> eval('[' + repr([[[1], 2], [3, 4]]).replace('[', '').replace(']', '') + ']')
      [1, 2, 3, 4]

      Otherwise, a recursive function is decently short:

      def flatten(lst):
          for elem in lst:
              if isinstance(elem, list):
                  yield from flatten(elem)
                  yield elem

      If you have deeply nested lists, I suppose you may want something like this:

      def flatten(lst):
          it = iter(lst)
          stack = [it]
          while stack:
                  elem = next(stack[-1])
              except StopIteration:
              if isinstance(elem, list):
                  yield elem
    6. 3

      Most frequent can be done with collections.Counter

      from collections import Counter
      counter = Counter('abracadabra')
      (most_common, _), *_ = counter.most_common(1)

      List flattening can be done with itertools.chain:

      from itertools  import chain
      list(chain.from_iterable(['abc', 'def']))

      The string module comes with constant containing all ascii letters for convenience:

      import string

      Contains all as implemented is quadratic. Best to convert list1 to a set first:

      set1 = set(list1)
      contains_all = all(elem in set1 for elem in list2)
    7. 2

      I tried to recreate this with Haskell “one-liners”:

      ghci> reverse "Hello World"
      "dlroW olleH"
      ghci> even 6
      ghci> import Data.List
      ghci> intersect [1, 2, 3] [2, 3, 4]
      ghci> nub [1, 2, 3, 2, 4, 3, 2, 1]
      ghci> sum $ map (const 1) [1, 2, 3, 4]
      ghci> null $ [1, 2, 3] \\ [1, 2, 3, 4]
      ghci> import System.Random
      ghci> getStdGen >>= return . take 10 . randomRs ('a', 'z')
      ghci> foldl1 (\a b -> 10*a + b) [1, 2, 3, 4]
      ghci> (\x -> x == reverse x) "racecar"
      ghci> concat [[1, 2], [3, 4]]
      [1, 2, 3, 4]
      ghci> head $ last $ sortOn length $ group $ sort [4,1,3,4,2,3,2,3,4,4]
      ghci> :module -Data.List
      ghci> import Data.Map
      ghci> union (fromList [('a', 1), ('b', 2)]) (fromList [('b', 3), ('c', 3)])
      fromList [('a',1),('b',2),('c',3)]

      And in oK:

        |"Hello World"
      "dlroW olleH"
        {x^x^y}[1 2 3;2 3 4]
      2 3
        ?1 2 3 2 4 3 2 1
      1 2 3 4
        +/{1}'1 2 3 4
        {~#x^y}[1 2 3;1 2 3 4]
        .,/$1 2 3 4
        ,//((1 2;3 4);(5;(6;7 8)))
      1 2 3 4 5 6 7 8
        *>=4 1 3 4 2 3 2 3 4 4
    8. 2

      the most frequent trick

      most_frequent = max(set(my_list), key=my_list.count)

      is “accidentally quadratic”, because my_list.count is a linear search and you’re doing it once for each distinct item.

      better to use collections.Counter

    9. 1

      Since a list can contain duplicate elements, should the intersection of 2 lists have the duplicates as well? I think this depend on the actual definition of the intersection, IIRC it is:

      for all x in a, x in “a&b” <=> x in b

      This would mean that for:

      a = [1, 2, 2, 3]
      b = [2, 3, 4]

      a&b should be [2, 2, 3] : 1 is not in b, 2 is in b, 2 is in b, 3 is in b. Note how it does not include the 2 and 3 that are in b.

      Am I mistaken?

      1. [Comment removed by author]

      2. 1

        Mathematically, intersection means the things that are in both lists. So I’d expect the output to contain two 2s only if both input lists do.

    10. 1

      next(g.gi_frame for _ in [1])

      It’s a fun one for candidate interviews “explain what happens here”

    11. 1

      Can anyone try this using lisp

    12. 1

      Are similar one-liners not possible in every well-used scripting language?

    13. 1

      The “remove duplicates from a list” example does not preserve order. I can’t think of a one-liner that does, since you need some kind of stateful iteration to keep track of unique elements and that probably warrants multiple lines.

      1. 2
        # or

        This is because since Python 3.7, dict is insertion-ordered, so dict.fromkeys() preserves the ordering. It’s slower though.

        EDIT: Also, note that it does not work with non-hashable items

        EDIT2: https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.unique_everseen

        1. 1

          in older 3.x releases you could explicitly use an OrderedDict. And the restriction to hashable elements also applies to the set-based implementation from the article I think?

          If you wanted to avoid that, you could do something hacky with reduce or a list comprehension, but it’d be inefficient due to having to do all the membership tests in lists.

        2. 1

          Nice! The set solution won’t work with non-hashable types anyway, right?