How to Map Over The Values of Zip2

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

  1. 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
  2. Convert your zip values from string to array. This is done to facilitate their _concatenation in the future. Done through the zipToArr function
  3. Group your array of objects under one object. In order to do that we promote the group key and concatenate zip1/zip2 with other objects from the same group. Refer to the grouper function
  4. Get the grouped objects using Object.values on the previous aggregate. We already have the group key in them so we don't need the parent key anymore
  5. 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 and format functions
  6. 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 element group

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(.)

zip code plot

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



Leave a reply



Submit