Last active
April 8, 2019 16:58
-
-
Save pdgonzalez872/1276c7edf11f47010194fb3f929a5d5f to your computer and use it in GitHub Desktop.
Elixir question on Slack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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