Skip to content

Instantly share code, notes, and snippets.

@pdgonzalez872
Last active April 8, 2019 16:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pdgonzalez872/1276c7edf11f47010194fb3f929a5d5f to your computer and use it in GitHub Desktop.
Save pdgonzalez872/1276c7edf11f47010194fb3f929a5d5f to your computer and use it in GitHub Desktop.
Elixir question on Slack
defmodule SlackQuestionTest do
@moduledoc """
Learning session!
Functions by `gregvaughn`
"""
use ExUnit.Case
@doc """
V1 by `gregvaughn`
"""
def v1(input) do
Enum.flat_map(input, fn outer ->
Enum.map(Enum.zip([outer.method, outer.param, outer.uri]), fn {m, p, u} ->
Map.merge(outer, %{method: m, param: p, uri: u})
end)
end)
end
@doc """
V2 by `gregvaughn`
"""
def v2(input) do
for outer <- input,
{m, p, u} <- Enum.zip([outer.method, outer.param, outer.uri]),
do: %{outer | method: m, param: p, uri: u}
end
@doc """
Uses v1 from `gregvaughn` and tries to explain, there is probably a better way of explaining...
"""
def attempt_to_explain(input) do
input
# Enum.flat_map/2 is a combination of Enum.map and a List.flatten. Very powerful!
# This will iterate through the input and then return one flattened list
|> Enum.flat_map(fn outer ->
# `outer` is one of the original maps
# Create a list with params coming from the map
[outer.method, outer.param, outer.uri]
# Enum.zip/1 combines ("zips") corresponding elements from a collection
# of enumerables into one list of tuples
# The result looks like [{"POST", "X-Content-Type-Options", "http://abc1.css"}, ...]
# We go from 1 map (the `outer`) to 3 elements in a list.
# This is the crux of this problem, where new things are created/allocated
|> Enum.zip()
# Now we iterate through those 3 elements, while pattern matching that tuple
# the tuple looks like this: {"POST", "X-Content-Type-Options", "abc3.min.css"}
|> Enum.map(fn {m, p, u} ->
# This will create a new map with updated keys
# This is one of the maps you wanted in your output
Map.merge(outer, %{method: m, param: p, uri: u})
end)
end)
end
setup do
input = [
%{
cweid: 100,
method: ["GET", "GET", "GET"],
name: "Hello",
param: ["X-XSS-Protection", "X-XSS-Protection", "X-XSS-Protection"],
riskcode: 1,
uri: ["http://xyz1.txt", "http://xyz2.com/", "http://xyz3x.html"]
},
%{
cweid: 500,
method: ["POST", "POST", "POST"],
name: "London",
param: ["X-Content-Type-Options", "X-Content-Type-Options", "X-Content-Type-Options"],
riskcode: 2,
uri: ["http://abc1.css", "http://abc2.jpg", "abc3.min.css"]
}
]
output = [
%{
cweid: 100,
method: "GET",
name: "Hello",
param: "X-XSS-Protection",
riskcode: 1,
uri: "http://xyz1.txt"
},
%{
cweid: 100,
method: "GET",
name: "Hello",
param: "X-XSS-Protection",
riskcode: 1,
uri: "http://xyz2.com/"
},
%{
cweid: 100,
method: "GET",
name: "Hello",
param: "X-XSS-Protection",
riskcode: 1,
uri: "http://xyz3x.html"
},
%{
cweid: 500,
method: "POST",
name: "London",
param: "X-Content-Type-Options",
riskcode: 2,
uri: "http://abc1.css"
},
%{
cweid: 500,
method: "POST",
name: "London",
param: "X-Content-Type-Options",
riskcode: 2,
uri: "http://abc2.jpg"
},
%{
cweid: 500,
method: "POST",
name: "London",
param: "X-Content-Type-Options",
riskcode: 2,
uri: "abc3.min.css"
}
]
{:ok, input: input, output: output}
end
test "v1 works", %{input: input, output: output} do
result = v1(input)
assert result == output
end
test "v2 works", %{input: input, output: output} do
result = v2(input)
assert result == output
end
test "attempt_to_explain", %{input: input, output: output} do
result = attempt_to_explain(input)
assert result == output
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment