I really like using Ruby's Array#dig
and Hash#dig
operator (introduced in Ruby 2.3) to quickly and safely access deeply nested structures
I would love to see different versions of it in other languages so I can use them more too!
Here's how dig works:
Assuming we have an orders
array that looks like this.
orders = [
{
id: 1,
customer: {
name: "Customer 1",
phone: "1234"
}
},
{
id: 2
},
# ...
]
We can easily navigate through this structure with dig
like so
orders.dig(0, :customer, :phone) #=> "1234"
We can also not worry about any of the "in-between" objects not existing, as it will return nil as soon it finds something that doesn't exist.
orders.dig(1, :customer, :phone) #=> nil
It returns nil
the moment it finds that customer
doesn't exist, and it makes me avoid checking if keys exist every time I want to access a nested object.
What are some cool ways to access nested data like this in other languages? I ask because I want to learn and because I probably do it in overly-convoluted ways at the moment.
Thanks for reading!
Top comments (14)
It's known as optional chaining / null propagation.
In Javascript it's described as ECMAScript proposal
instead of writing:
it could be like:
For now, there are libraries like lodash/get, where we can use function:
For Python, glom is a great package for this sort of nested data access. The happy path from the intro docs looks like this:
That
'a.b.c'
bit is a simple glom specifier, but it can get much wilder! Glom provides more advanced specifiers for features like:And you can always plug in your own code or extend glom even further. Simple to get started, but a long fun road to travel from there!
PHP7 introduced the null coalesce operator (
??
) which will suppress errors for the missing intermediate keys. So, this will work without errors/warnings:The Laravel framework in PHP also has array helpers which allow you to access values using "dot" notation:
You can pass a third value to use as the default if it doesn't exist, but the default is
null
without it.This helper function is a shortcut to access the
Arr::get()
method mentioned by Suhayb Alghutaymil.I'm currently doing Rust, and I have a little trouble answering this question.
A couple points:
dig
built-in.nil
/null
/whatever in Rust - if it's aString
, it's there, no strings attached (pun intended).Option
enum, which can be eitherSome(value)
orNone
(the concept is not new - Haskell hasMaybe
, and languages like Swift or Kotlin have nullable types)Options
.I came up with this:
Looks a bit funky, but does the job:
EDIT: I completely forgot about a cool language feature in Rust -
?
operator.Synopsis:
Result<T, E>
is very similar toOption<T>
, but it instead can be eitherOk(T)
(all good,T
is the value) orErr(E)
(something went wrong,E
is the error type -String
for a message, etc.)result?
basically means .if it's Ok, get the inner value and continue execution. If it's an Err,return
it".It allows for code like this:
C# 6.0 and onwards gives you the Null Propagating Operator MSDN Guide β like many of the other languages here, you would use it something like:
This can be combined with the null coalescing operator, to give a default value:
In Laravel you could use this with Arr::get helper method.
In Java (version 8 and onward) this can be done using Optional
Haskell and other functional languages have Lenses, which are roughly equivalent to focusing on a value or path and either getting or setting it. Imagine
dig
with a relatedbury
function and you get close.I'd mentioned it in this particular Storybook post in Part Four, though it may make more sense to start at Part One for continuity
In Elixir use Kernel.get_in/2 for maps
Kotlin
See this runnable snippet pl.kotl.in/1aOqY8rQu