How do you map over the values of Zip2?
The following will get you an array from the return value of Zip2:
var myZip = Zip2([1, 2, 3], ["a", "b", "c"]).generate()
var myZipArray: Array<(Int, String)> = []
while let elem = myZip.next() {
myZipArray += elem
}
println(myZipArray) // [(1, a), (2, b), (3, c)]
-- UPDATE: EVEN BETTER! --
let myZip = Zip2([1, 2, 3], ["a", "b", "c"])
let myZipArray = Array(myZip)
println(myZipArray) // [(1, a), (2, b), (3, c)]
-- now for fun --
I'm going to guess that we can init a new Array with anything that responds to generate()
?
println(Array("abcde")) // [a, b, c, d, e]
How to push all values into array and get them with javascript
Methodology
- Convert your 2D array into a 1D array, so instead of having arrays as inner items you will have objects. This is done through the
arrToObj
function - Convert your
zip
values from string to array. This is done to facilitate their _concatenation in the future. Done through thezipToArr
function - Group your array of objects under one object. In order to do that we promote the
group
key and concatenatezip1/zip2
with other objects from the same group. Refer to thegrouper
function - Get the grouped objects using
Object.values
on the previous aggregate. We already have thegroup
key in them so we don't need the parent key anymore - Format your values into HTML elements based on their respective keys. This will facilitate generating the HTML in the end since we'll have the elements ready. Done with
html
andformat
functions - Render your HTML by iterating on the previously generated array. In each iteration create a container
div
that will hold the group. The container will help styling its first elementgroup
Implementation
const array = [[{"loc":{}},{"distance":6.4},{"zip1":"06120"},{"zip2":"06095"},{"group":1},{"weight":1119}],[{"loc":{}},{"distance":6.41},{"zip1":"06095"},{"zip2":"06120"},{"group":2},{"weight":41976}],[{"loc":{}},{"distance":6.41},{"zip1":"06095"},{"zip2":"06120"},{"group":1},{"weight":41976}]];
// Data processing functions
const arrToObj = arr => arr.reduce((a, c) => ({ ...a, ...c}), {});
const zipToArr = x => ({...x, zip1: [x.zip1], zip2: [x.zip2]});
const grouper = (a, c) => {
delete c.loc;
delete c.distance;
if (a[c.group]) {
a[c.group].zip1.push(...c.zip1);
a[c.group].zip2.push(...c.zip2);
return a;
} else {
return {...a, [c.group]: c}
}
};
// HTML utilities
const html = (k, v) => {
const it = document.createElement('p');
it.innerHTML = `${k} ${v}`;
return it;
}
const format = g => Object.keys(g).sort().reduce((a, c) => ({...a, [c]: html(c, g[c])}), {});
// Actual processing
const data = array.map(arrToObj).map(zipToArr).reduce(grouper, {});
const dataWithHTML = Object.values(data).map(format);
// Rendering
const display = document.getElementById('display');
dataWithHTML.forEach(it => {
const container = document.createElement('div');
Object.values(it).forEach(v => container.appendChild(v));
display.appendChild(container);
});
p:first-of-type {
font-size: 36px;
font-weight: bold;
margin: 0;
}
p {
text-transform: capitalize;
}
<div id="display"></div>
How do I zip two arrays in JavaScript?
Use the map
method:
var a = [1, 2, 3]var b = ['a', 'b', 'c']
var c = a.map(function(e, i) { return [e, b[i]];});
console.log(c)
How do you join two arrays in Swift combing and preserving the order of each array? (Interleaving arrays in swift)
UPDATE 12/16/2015: Not sure why I didn't recognize that flatMap was a good candidate here. Perhaps it wasn't in the core library at the time? Anyway the map/reduce can be replaced with one call to flatMap. Also Zip2 has been renamed. The new solution is
let c = Zip2Sequence(a,b).flatMap{[$0, $1]}
And if you run this in the swift repl environment:
> let c = Zip2Sequence(a,b).flatMap{[$0, $1]}
c: [String] = 6 values {
[0] = "Icon1"
[1] = "icon1.png"
[2] = "Icon2"
[3] = "icon2.png"
[4] = "Icon3"
[5] = "icon3.png"
}
Original answer below:
Here's one way I whipped together for fun
let c = map(Zip2(a,b), { t in
[t.0, t.1]
})
let d = c.reduce([], +)
or inlining
let c = map(Zip2(a,b), { t in
[t.0, t.1]
}).reduce([], +)
The zipping seems unnecessary. I imagine there's a better way of doing that. But basically, I'm zipping them together, then converting each tuple into an array, and then flattening the array of arrays.
Finally, a little shorter:
let c = map(Zip2(a,b)){ [$0.0, $0.1] }.reduce([], +)
Draw a line between 2 zip code on US map in R
Take a look at the code for zip.plot
function, and you'll see it is straightforward. It will merge your zip code data with longitude and latitude data from data(zips)
. You'll notice it will plot points, but no function to connect them, and it doesn't return points plotted.
You could adapt a similar function that meets your needs. If you include library(muRL)
you can load zip data by data(zips)
. After plotting the points, you can add lines to connect them based on trip
variable.
For example, create a new function zip.plot.new
:
library(muRL)
data(zips)
zip.plot.new <- function(data, map.type = "state", ...){
data.z <- merge(data, zips[,c("zip", "lat", "lon")], by.x = "zip", by.y = "zip", all.x = TRUE)
maps::map(map.type, ...)
points(data.z$lon, data.z$lat, cex = 1, col = "black", pch = 20)
mapply(lines, split(data.z$lon, data.z$trip), split(data.z$lat, data.z$trip))
}
This includes mapply(lines...
to connect points by trip
.
Then, you can use your data frame, convert to longer form, and call this new function:
library(tidyverse)
df1 %>%
pivot_longer(cols = starts_with("zip_"), names_to = c(".value", "group"), names_sep = "_") %>%
zip.plot.new(.)
Note that zip code 12909
was not matched in the data (appears not valid?).
Data
df1 <- data.frame(trip = c(1,2,3,4),
zip_1 = c("55803","87112","55107","66006"),
zip_2 = c("12909","93703","12205","78210"))
Edit: Here's a ggplot
version:
library(ggmap)
library(maps)
library(ggplot2)
library(tidyverse)
MainStates <- map_data("state")
point_data <- df1 %>%
pivot_longer(cols = starts_with("zip_"), names_to = c(".value", "group"), names_sep = "_") %>%
mutate(zip = factor(zip, levels = levels(zips$zip))) %>%
left_join(zips)
ggplot() +
geom_polygon(data=MainStates, aes(x=long, y=lat, group=group), color = "black", fill = "white") +
geom_point(data = point_data, aes(x = lon, y = lat, group = trip)) +
geom_line(data = point_data, aes(x = lon, y = lat, group = trip)) +
coord_fixed(1.3) +
theme_nothing()
Sort Array based on other Sorted Array
Zip2
, sorted
and map
array1 = map(sorted(Zip2(array1, array2), {$0.1 > $1.1}), { $0.0 })
Combining filter
var array1 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
var array2 = [5, 2, 3, 4, 5, 6, 8, 5, 4, 5, 1]
func isEven(x:Int) -> Bool {
return x % 2 == 0
}
let result = map(sorted(filter(Zip2(array1, array2), { isEven($0.1) }), {$0.1 > $1.1}), { $0.0 })
// -> ["6", "5", "3", "8", "1"]
As you can see, the line is too complex, you might want to Array
method chain syntax:
let result2 = Array(Zip2(array1, array2))
.filter({ isEven($0.1) })
.sorted({ $0.1 > $1.1 })
.map({ $0.0 })
Anyway, if your array2
is [PFObject]
, you can implement the function something like:
func isOpen(restaurant: PFObject, forTime time: String, onDay day: Int) -> Bool {
// return `true` if the restaurant is open, `false` otherwise
}
Scheme Vector Syntax
I don't think the result is correct. If we run the procedure in the question, this is what we get:
(zip2 '(1 2 3) '(4 5 6))
=> '#(#(1 4) #(#(2 5) #(#(3 6) ())))
As you can see, there are vectors nested within vectors, deeper than they should. The problem with your solution is that you can't just replace cons
with vector
and expect that things will work the same; cons
is fine for building a list as you go, adding one element at a time, but for building a vector you need to know all the elements beforehand, because you can't add elements after its creation.
I'd rather solve the problem in terms of the "normal" zip
operation (the one that uses lists) and then convert the result to vectors:
(define (zip list1 list2)
(map list list1 list2))
(zip '(1 2 3) '(4 5 6))
=> '((1 4) (2 5) (3 6))
(define (zip2 list1 list2)
(list->vector
(map list->vector (zip list1 list2))))
(zip2 '(1 2 3) '(4 5 6))
=> '#(#(1 4) #(2 5) #(3 6))
Or equivalently, but without using zip
as part of the solution:
(define (zip2 list1 list2)
(list->vector
(map vector list1 list2)))
(zip2 '(1 2 3) '(4 5 6))
=> '#(#(1 4) #(2 5) #(3 6))
Transform from dictionary to array in swift without a for loop
Using the ideas and the dictionary extension
extension Dictionary {
init(_ pairs: [Element]) {
self.init()
for (k, v) in pairs {
self[k] = v
}
}
func map<OutKey: Hashable, OutValue>(transform: Element -> (OutKey, OutValue)) -> [OutKey: OutValue] {
return Dictionary<OutKey, OutValue>(Swift.map(self, transform))
}
}
from
- What's the cleanest way of applying map() to a dictionary in Swift?,
you could achieve this with
let count = returnedFromServer["time"]!.count
let outputArray = (0 ..< count).map {
idx -> [String: AnyObject] in
return returnedFromServer.map {
(key, value) in
return (key, value[idx])
}
}
Related Topics
Programmatically Place Partial Image Over Another in UIview Using Swift 3
Swift: How to Add a Class Method in 'string" Extension
Is There a Method to Check The UIcollectionview Item Drag Cancellation If The Item Wasn't Moved
Mapping Swift Combine Future to Another Future
Override UIgesturerecognizer Touchesbegan
Cocoa: Simulating Command+Tab in Cgevent
Include Dictionary or Array Value in Swift String with Backslash Notation
What's The Difference Between [String] VS. [(String)]
How to Change Orientation for Avcapturemoviefileoutput in Swift
Custom Radix Columns (+Special Characters)
More Precision Than Double in Swift
Table View's 'Cellforrow(At:)' Is 'Nil' in Unit Test
Protocol Associated Type Typealias Assignment Compile Error
How to Put View on Top of All Other Views in Swiftui
Reachability Change Notification Should Be Called Only Once
Combine Sink: Ignore Receivevalue, Only Completion Is Needed