├── .gitignore ├── README.md ├── cities.json ├── index.js ├── package-lock.json ├── package.json ├── percentile.js └── values.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Companion Source for Ramda Tutorial 2 | 3 | **"What's Ramda?"** 4 | 5 | Ramda is a Functional Programming library for JavaScript, that is simlar to Lodash and Underscore. 6 | 7 | **"What's different about Ramda vs. Lodash?"** 8 | 9 | Ramda follows many Functional Principles such as: 10 | 11 | * Functional Purity 12 | * Immutability 13 | * Currying 14 | * Composition 15 | 16 | **"Ok, big deal! Why should I care?"** 17 | 18 | There's many reasons, but if I had to give you one, I'd say: 19 | It provides a nice, simple way to build sophisticated logic through function composition. 20 | 21 | **"What's function composition?"** 22 | 23 | It's a way to create new functions by combining two or more pure functions. I like to think of it as creating new functions without having to add new logic. 24 | 25 | **"This seems interesting, where can I learn more?"** 26 | 27 | If Ramda and functional programming looks interesting, and you want to learn more, please consider taking my course ["Functional Programming For Beginners with JavaScript"](https://knowthen.com/fp) 28 | -------------------------------------------------------------------------------- /cities.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Bangkok", 4 | "country": "TH", 5 | "region": "SE Asia", 6 | "cost": 1380, 7 | "currency": "USD", 8 | "temp": 302.03888888888895, 9 | "humidity": 78, 10 | "internetSpeed": 20 11 | }, 12 | { 13 | "name": "Chiang Mai", 14 | "country": "TH", 15 | "region": "SE Asia", 16 | "cost": 654, 17 | "currency": "USD", 18 | "temp": 299.8166666666667, 19 | "humidity": 83, 20 | "internetSpeed": 20 21 | }, 22 | { 23 | "name": "Pattaya", 24 | "country": "TH", 25 | "region": "SE Asia", 26 | "cost": 1183, 27 | "currency": "USD", 28 | "temp": 301.48333333333335, 29 | "humidity": 88, 30 | "internetSpeed": 20 31 | }, 32 | { 33 | "name": "Phuket", 34 | "country": "TH", 35 | "region": "SE Asia", 36 | "cost": 1040, 37 | "currency": "USD", 38 | "temp": 302.03888888888895, 39 | "humidity": 74, 40 | "internetSpeed": 20 41 | }, 42 | { 43 | "name": "Hoi An", 44 | "country": "VN", 45 | "region": "SE Asia", 46 | "cost": 1083, 47 | "currency": "USD", 48 | "temp": 299.2611111111112, 49 | "humidity": 83, 50 | "internetSpeed": 20 51 | }, 52 | { 53 | "name": "Prague", 54 | "country": "CZ", 55 | "region": "Europe", 56 | "cost": 1191, 57 | "currency": "USD", 58 | "temp": 292.03888888888895, 59 | "humidity": 77, 60 | "internetSpeed": 40 61 | }, 62 | { 63 | "name": "Phnom Penh", 64 | "country": "KH", 65 | "region": "SE Asia", 66 | "cost": 936, 67 | "currency": "USD", 68 | "temp": 301.48333333333335, 69 | "humidity": 78, 70 | "internetSpeed": 10 71 | }, 72 | { 73 | "name": "Sofia", 74 | "country": "BG", 75 | "region": "Europe", 76 | "cost": 1490, 77 | "currency": "USD", 78 | "temp": 296.48333333333335, 79 | "humidity": 69, 80 | "internetSpeed": 40 81 | }, 82 | { 83 | "name": "Riga", 84 | "country": "LV", 85 | "region": "Europe", 86 | "cost": 1417, 87 | "currency": "USD", 88 | "temp": 286.48333333333335, 89 | "humidity": 82, 90 | "internetSpeed": 40 91 | }, 92 | { 93 | "name": "Ho Chi Minh City", 94 | "country": "VN", 95 | "region": "SE Asia", 96 | "cost": 1329, 97 | "currency": "USD", 98 | "temp": 296.48333333333335, 99 | "humidity": 97, 100 | "internetSpeed": 20 101 | }, 102 | { 103 | "name": "Penang", 104 | "country": "MY", 105 | "region": "SE Asia", 106 | "cost": 1065, 107 | "currency": "USD", 108 | "temp": 301.48333333333335, 109 | "humidity": 83, 110 | "internetSpeed": 10 111 | }, 112 | { 113 | "name": "Budapest", 114 | "country": "HU", 115 | "region": "Europe", 116 | "cost": 2166, 117 | "currency": "USD", 118 | "temp": 298.15000000000003, 119 | "humidity": 53, 120 | "internetSpeed": 30 121 | }, 122 | { 123 | "name": "Kuala Lumpur", 124 | "country": "MY", 125 | "region": "SE Asia", 126 | "cost": 1206, 127 | "currency": "USD", 128 | "temp": 299.2611111111112, 129 | "humidity": 83, 130 | "internetSpeed": 10 131 | }, 132 | { 133 | "name": "Brasov", 134 | "country": "RO", 135 | "region": "Europe", 136 | "cost": 1824, 137 | "currency": "USD", 138 | "temp": 294.2611111111112, 139 | "humidity": 57, 140 | "internetSpeed": 80 141 | }, 142 | { 143 | "name": "Bratislava", 144 | "country": "SK", 145 | "region": "Europe", 146 | "cost": 1551, 147 | "currency": "USD", 148 | "temp": 294.2611111111112, 149 | "humidity": 82, 150 | "internetSpeed": 20 151 | }, 152 | { 153 | "name": "Kosice", 154 | "country": "SK", 155 | "region": "Europe", 156 | "cost": 1466, 157 | "currency": "USD", 158 | "temp": 292.03888888888895, 159 | "humidity": 72, 160 | "internetSpeed": 30 161 | }, 162 | { 163 | "name": "Belgrade", 164 | "country": "RS", 165 | "region": "Europe", 166 | "cost": 1358, 167 | "currency": "USD", 168 | "temp": 293.15000000000003, 169 | "humidity": 93, 170 | "internetSpeed": 10 171 | }, 172 | { 173 | "name": "Wroclaw", 174 | "country": "PL", 175 | "region": "Europe", 176 | "cost": 1764, 177 | "currency": "USD", 178 | "temp": 294.2611111111112, 179 | "humidity": 68, 180 | "internetSpeed": 20 181 | }, 182 | { 183 | "name": "Davao", 184 | "country": "PH", 185 | "region": "SE Asia", 186 | "cost": 1054, 187 | "currency": "USD", 188 | "temp": 294.8166666666667, 189 | "humidity": 100, 190 | "internetSpeed": 5 191 | }, 192 | { 193 | "name": "Timisoara", 194 | "country": "RO", 195 | "region": "Europe", 196 | "cost": 1999, 197 | "currency": "USD", 198 | "temp": 294.2611111111112, 199 | "humidity": 94, 200 | "internetSpeed": 60 201 | }, 202 | { 203 | "name": "Ubud", 204 | "country": "ID", 205 | "region": "SE Asia", 206 | "cost": 1185, 207 | "currency": "USD", 208 | "temp": 298.15000000000003, 209 | "humidity": 83, 210 | "internetSpeed": 5 211 | }, 212 | { 213 | "name": "Ljubljana", 214 | "country": "SI", 215 | "region": "Europe", 216 | "cost": 2162, 217 | "currency": "USD", 218 | "temp": 293.15000000000003, 219 | "humidity": 77, 220 | "internetSpeed": 20 221 | }, 222 | { 223 | "name": "Warsaw", 224 | "country": "PL", 225 | "region": "Europe", 226 | "cost": 1987, 227 | "currency": "USD", 228 | "temp": 291.48333333333335, 229 | "humidity": 63, 230 | "internetSpeed": 30 231 | }, 232 | { 233 | "name": "Zagreb", 234 | "country": "HR", 235 | "region": "Europe", 236 | "cost": 1539, 237 | "currency": "USD", 238 | "temp": 295.37222222222226, 239 | "humidity": 82, 240 | "internetSpeed": 10 241 | }, 242 | { 243 | "name": "Shanghai", 244 | "country": "CN", 245 | "region": "East Asia", 246 | "cost": 1656, 247 | "currency": "USD", 248 | "temp": 298.15000000000003, 249 | "humidity": 83, 250 | "internetSpeed": 20 251 | }, 252 | { 253 | "name": "San Juan", 254 | "country": "US", 255 | "region": "Central America", 256 | "cost": 2164, 257 | "currency": "USD", 258 | "temp": 297.03888888888895, 259 | "humidity": 94, 260 | "internetSpeed": 10 261 | }, 262 | { 263 | "name": "Cochabamba", 264 | "country": "BO", 265 | "region": "South America", 266 | "cost": 829, 267 | "currency": "USD", 268 | "temp": 297.03888888888895, 269 | "humidity": 25, 270 | "internetSpeed": 5 271 | }, 272 | { 273 | "name": "Taipei", 274 | "country": "TW", 275 | "region": "East Asia", 276 | "cost": 2137, 277 | "currency": "USD", 278 | "temp": 304.8166666666667, 279 | "humidity": 69, 280 | "internetSpeed": 40 281 | }, 282 | { 283 | "name": "Montreal", 284 | "country": "CA", 285 | "region": "North America", 286 | "cost": 2305, 287 | "currency": "USD", 288 | "temp": 297.5944444444445, 289 | "humidity": 57, 290 | "internetSpeed": 20 291 | }, 292 | { 293 | "name": "Las Vegas", 294 | "country": "US", 295 | "region": "North America", 296 | "cost": 2148, 297 | "currency": "USD", 298 | "temp": 307.5944444444445, 299 | "humidity": 20, 300 | "internetSpeed": 40 301 | }, 302 | { 303 | "name": "Lima", 304 | "country": "PE", 305 | "region": "South America", 306 | "cost": 1099, 307 | "currency": "USD", 308 | "temp": 292.03888888888895, 309 | "humidity": 72, 310 | "internetSpeed": 10 311 | }, 312 | { 313 | "name": "Curitiba", 314 | "country": "BR", 315 | "region": "South America", 316 | "cost": 2145, 317 | "currency": "USD", 318 | "temp": 299.8166666666667, 319 | "humidity": 60, 320 | "internetSpeed": 30 321 | }, 322 | { 323 | "name": "Siem Reap", 324 | "country": "KH", 325 | "region": "SE Asia", 326 | "cost": 1045, 327 | "currency": "USD", 328 | "temp": 299.2611111111112, 329 | "humidity": 78, 330 | "internetSpeed": 10 331 | }, 332 | { 333 | "name": "Austin", 334 | "country": "US", 335 | "region": "North America", 336 | "cost": 2541, 337 | "currency": "USD", 338 | "temp": 299.2611111111112, 339 | "humidity": 73, 340 | "internetSpeed": 60 341 | }, 342 | { 343 | "name": "Beijing", 344 | "country": "CN", 345 | "region": "East Asia", 346 | "cost": 1565, 347 | "currency": "USD", 348 | "temp": 300.9277777777778, 349 | "humidity": 93, 350 | "internetSpeed": 30 351 | }, 352 | { 353 | "name": "Cairo", 354 | "country": "EG", 355 | "region": "Africa", 356 | "cost": 917, 357 | "currency": "USD", 358 | "temp": 305.37222222222226, 359 | "humidity": 38, 360 | "internetSpeed": 5 361 | }, 362 | { 363 | "name": "Dallas", 364 | "country": "US", 365 | "region": "North America", 366 | "cost": 2265, 367 | "currency": "USD", 368 | "temp": 306.48333333333335, 369 | "humidity": 55, 370 | "internetSpeed": 20 371 | }, 372 | { 373 | "name": "Park City", 374 | "country": "US", 375 | "region": "North America", 376 | "cost": 2862, 377 | "currency": "USD", 378 | "temp": 302.03888888888895, 379 | "humidity": 21, 380 | "internetSpeed": 40 381 | }, 382 | { 383 | "name": "Lisbon", 384 | "country": "PT", 385 | "region": "Europe", 386 | "cost": 2455, 387 | "currency": "USD", 388 | "temp": 300.37222222222226, 389 | "humidity": 64, 390 | "internetSpeed": 30 391 | }, 392 | { 393 | "name": "Santa Monica", 394 | "country": "US", 395 | "region": "North America", 396 | "cost": 2601, 397 | "currency": "USD", 398 | "temp": 302.03888888888895, 399 | "humidity": 69, 400 | "internetSpeed": 40 401 | }, 402 | { 403 | "name": "Singapore", 404 | "country": "SG", 405 | "region": "SE Asia", 406 | "cost": 2678, 407 | "currency": "USD", 408 | "temp": 298.15000000000003, 409 | "humidity": 94, 410 | "internetSpeed": 80 411 | }, 412 | { 413 | "name": "Medellin", 414 | "country": "CO", 415 | "region": "South America", 416 | "cost": 1296, 417 | "currency": "USD", 418 | "temp": 294.2611111111112, 419 | "humidity": 52, 420 | "internetSpeed": 10 421 | }, 422 | { 423 | "name": "Toronto", 424 | "country": "CA", 425 | "region": "North America", 426 | "cost": 2825, 427 | "currency": "USD", 428 | "temp": 300.37222222222226, 429 | "humidity": 69, 430 | "internetSpeed": 20 431 | }, 432 | { 433 | "name": "Tokyo", 434 | "country": "JP", 435 | "region": "East Asia", 436 | "cost": 2392, 437 | "currency": "USD", 438 | "temp": 298.15000000000003, 439 | "humidity": 83, 440 | "internetSpeed": 30 441 | }, 442 | { 443 | "name": "Porto", 444 | "country": "PT", 445 | "region": "Europe", 446 | "cost": 2686, 447 | "currency": "USD", 448 | "temp": 299.2611111111112, 449 | "humidity": 99, 450 | "internetSpeed": 30 451 | }, 452 | { 453 | "name": "Tucson", 454 | "country": "US", 455 | "region": "North America", 456 | "cost": 2882, 457 | "currency": "USD", 458 | "temp": 309.8166666666667, 459 | "humidity": 31, 460 | "internetSpeed": 30 461 | }, 462 | { 463 | "name": "Palawan", 464 | "country": "PH", 465 | "region": "SE Asia", 466 | "cost": 1255, 467 | "currency": "USD", 468 | "temp": 295.9277777777778, 469 | "humidity": 96, 470 | "internetSpeed": 5 471 | }, 472 | { 473 | "name": "Hong Kong", 474 | "country": "HK", 475 | "region": "East Asia", 476 | "cost": 2634, 477 | "currency": "USD", 478 | "temp": 304.8166666666667, 479 | "humidity": 79, 480 | "internetSpeed": 90 481 | }, 482 | { 483 | "name": "Playa del Carmen", 484 | "country": "MX", 485 | "region": "North America", 486 | "cost": 1887, 487 | "currency": "USD", 488 | "temp": 303.7055555555556, 489 | "humidity": 70, 490 | "internetSpeed": 10 491 | }, 492 | { 493 | "name": "Manchester", 494 | "country": "UK", 495 | "region": "Europe", 496 | "cost": 2641, 497 | "currency": "USD", 498 | "temp": 294.2611111111112, 499 | "humidity": 64, 500 | "internetSpeed": 30 501 | }, 502 | { 503 | "name": "Tel Aviv", 504 | "country": "IL", 505 | "region": "Europe", 506 | "cost": 2519, 507 | "currency": "USD", 508 | "temp": 301.48333333333335, 509 | "humidity": 61, 510 | "internetSpeed": 20 511 | }, 512 | { 513 | "name": "Bucharest", 514 | "country": "RO", 515 | "region": "Europe", 516 | "cost": 2064, 517 | "currency": "USD", 518 | "temp": 295.37222222222226, 519 | "humidity": 77, 520 | "internetSpeed": 80 521 | }, 522 | { 523 | "name": "Vancouver", 524 | "country": "CA", 525 | "region": "North America", 526 | "cost": 2843, 527 | "currency": "USD", 528 | "temp": 292.5944444444445, 529 | "humidity": 87, 530 | "internetSpeed": 40 531 | }, 532 | { 533 | "name": "Bordeaux", 534 | "country": "FR", 535 | "region": "Europe", 536 | "cost": 3077, 537 | "currency": "USD", 538 | "temp": 300.9277777777778, 539 | "humidity": 36, 540 | "internetSpeed": 30 541 | }, 542 | { 543 | "name": "Buenos Aires", 544 | "country": "AR", 545 | "region": "South America", 546 | "cost": 1724, 547 | "currency": "USD", 548 | "temp": 291.48333333333335, 549 | "humidity": 88, 550 | "internetSpeed": 10 551 | }, 552 | { 553 | "name": "Detroit", 554 | "country": "US", 555 | "region": "North America", 556 | "cost": 2301, 557 | "currency": "USD", 558 | "temp": 300.37222222222226, 559 | "humidity": 44, 560 | "internetSpeed": 30 561 | }, 562 | { 563 | "name": "Seoul", 564 | "country": "KR", 565 | "region": "East Asia", 566 | "cost": 2934, 567 | "currency": "USD", 568 | "temp": 293.15000000000003, 569 | "humidity": 82, 570 | "internetSpeed": 60 571 | }, 572 | { 573 | "name": "Cebu", 574 | "country": "PH", 575 | "region": "SE Asia", 576 | "cost": 1808, 577 | "currency": "USD", 578 | "temp": 299.2611111111112, 579 | "humidity": 88, 580 | "internetSpeed": 5 581 | }, 582 | { 583 | "name": "Tallinn", 584 | "country": "EE", 585 | "region": "Europe", 586 | "cost": 3161, 587 | "currency": "USD", 588 | "temp": 289.2611111111112, 589 | "humidity": 82, 590 | "internetSpeed": 40 591 | }, 592 | { 593 | "name": "Boulder", 594 | "country": "US", 595 | "region": "North America", 596 | "cost": 3070, 597 | "currency": "USD", 598 | "temp": 307.5944444444445, 599 | "humidity": 20, 600 | "internetSpeed": 20 601 | }, 602 | { 603 | "name": "Salzburg", 604 | "country": "AT", 605 | "region": "Europe", 606 | "cost": 2748, 607 | "currency": "USD", 608 | "temp": 290.9277777777778, 609 | "humidity": 82, 610 | "internetSpeed": 20 611 | }, 612 | { 613 | "name": "Madrid", 614 | "country": "ES", 615 | "region": "Europe", 616 | "cost": 2798, 617 | "currency": "USD", 618 | "temp": 308.15000000000003, 619 | "humidity": 17, 620 | "internetSpeed": 30 621 | }, 622 | { 623 | "name": "Vienna", 624 | "country": "AT", 625 | "region": "Europe", 626 | "cost": 3096, 627 | "currency": "USD", 628 | "temp": 292.5944444444445, 629 | "humidity": 82, 630 | "internetSpeed": 20 631 | }, 632 | { 633 | "name": "Manila", 634 | "country": "PH", 635 | "region": "SE Asia", 636 | "cost": 1371, 637 | "currency": "USD", 638 | "temp": 298.15000000000003, 639 | "humidity": 100, 640 | "internetSpeed": 5 641 | }, 642 | { 643 | "name": "Dubai", 644 | "country": "AE", 645 | "region": "Middle East", 646 | "cost": 3233, 647 | "currency": "USD", 648 | "temp": 309.2611111111112, 649 | "humidity": 37, 650 | "internetSpeed": 30 651 | }, 652 | { 653 | "name": "Recife", 654 | "country": "BR", 655 | "region": "South America", 656 | "cost": 1994, 657 | "currency": "USD", 658 | "temp": 299.2611111111112, 659 | "humidity": 97, 660 | "internetSpeed": 20 661 | }, 662 | { 663 | "name": "Saint Petersburg", 664 | "country": "RU", 665 | "region": "Europe", 666 | "cost": 2124, 667 | "currency": "USD", 668 | "temp": 289.2611111111112, 669 | "humidity": 63, 670 | "internetSpeed": 20 671 | }, 672 | { 673 | "name": "Orlando", 674 | "country": "US", 675 | "region": "North America", 676 | "cost": 2436, 677 | "currency": "USD", 678 | "temp": 306.48333333333335, 679 | "humidity": 55, 680 | "internetSpeed": 20 681 | }, 682 | { 683 | "name": "Seattle", 684 | "country": "US", 685 | "region": "North America", 686 | "cost": 3254, 687 | "currency": "USD", 688 | "temp": 292.03888888888895, 689 | "humidity": 72, 690 | "internetSpeed": 30 691 | }, 692 | { 693 | "name": "Salt Lake City", 694 | "country": "US", 695 | "region": "North America", 696 | "cost": 3729, 697 | "currency": "USD", 698 | "temp": 301.48333333333335, 699 | "humidity": 20, 700 | "internetSpeed": 30 701 | }, 702 | { 703 | "name": "Berlin", 704 | "country": "DE", 705 | "region": "Europe", 706 | "cost": 3508, 707 | "currency": "USD", 708 | "temp": 293.7055555555556, 709 | "humidity": 49, 710 | "internetSpeed": 30 711 | }, 712 | { 713 | "name": "Wellington", 714 | "country": "NZ", 715 | "region": "Oceania", 716 | "cost": 3539, 717 | "currency": "USD", 718 | "temp": 284.2611111111111, 719 | "humidity": 87, 720 | "internetSpeed": 30 721 | }, 722 | { 723 | "name": "Cambridge", 724 | "country": "UK", 725 | "region": "Europe", 726 | "cost": 3270, 727 | "currency": "USD", 728 | "temp": 295.37222222222226, 729 | "humidity": 49, 730 | "internetSpeed": 30 731 | }, 732 | { 733 | "name": "Portland", 734 | "country": "US", 735 | "region": "North America", 736 | "cost": 3266, 737 | "currency": "USD", 738 | "temp": 289.8166666666667, 739 | "humidity": 62, 740 | "internetSpeed": 20 741 | }, 742 | { 743 | "name": "Granada", 744 | "country": "ES", 745 | "region": "Europe", 746 | "cost": 2855, 747 | "currency": "USD", 748 | "temp": 301.48333333333335, 749 | "humidity": 25, 750 | "internetSpeed": 30 751 | }, 752 | { 753 | "name": "Barcelona", 754 | "country": "ES", 755 | "region": "Europe", 756 | "cost": 3431, 757 | "currency": "USD", 758 | "temp": 298.15000000000003, 759 | "humidity": 60, 760 | "internetSpeed": 30 761 | }, 762 | { 763 | "name": "Dublin", 764 | "country": "IE", 765 | "region": "Europe", 766 | "cost": 3214, 767 | "currency": "USD", 768 | "temp": 290.37222222222226, 769 | "humidity": 82, 770 | "internetSpeed": 30 771 | }, 772 | { 773 | "name": "Auckland", 774 | "country": "NZ", 775 | "region": "Oceania", 776 | "cost": 2869, 777 | "currency": "USD", 778 | "temp": 284.8166666666667, 779 | "humidity": 100, 780 | "internetSpeed": 20 781 | }, 782 | { 783 | "name": "Stockholm", 784 | "country": "SE", 785 | "region": "Europe", 786 | "cost": 3714, 787 | "currency": "USD", 788 | "temp": 295.37222222222226, 789 | "humidity": 68, 790 | "internetSpeed": 50 791 | }, 792 | { 793 | "name": "Denver", 794 | "country": "US", 795 | "region": "North America", 796 | "cost": 3229, 797 | "currency": "USD", 798 | "temp": 307.5944444444445, 799 | "humidity": 20, 800 | "internetSpeed": 30 801 | }, 802 | { 803 | "name": "Basel", 804 | "country": "CH", 805 | "region": "Europe", 806 | "cost": 3795, 807 | "currency": "USD", 808 | "temp": 291.48333333333335, 809 | "humidity": 82, 810 | "internetSpeed": 40 811 | }, 812 | { 813 | "name": "Amsterdam", 814 | "country": "NL", 815 | "region": "Europe", 816 | "cost": 3772, 817 | "currency": "USD", 818 | "temp": 293.7055555555556, 819 | "humidity": 68, 820 | "internetSpeed": 40 821 | }, 822 | { 823 | "name": "Johannesburg", 824 | "country": "ZA", 825 | "region": "Africa", 826 | "cost": 2072, 827 | "currency": "USD", 828 | "temp": 293.15000000000003, 829 | "humidity": 12, 830 | "internetSpeed": 10 831 | }, 832 | { 833 | "name": "Lyon", 834 | "country": "FR", 835 | "region": "Europe", 836 | "cost": 3680, 837 | "currency": "USD", 838 | "temp": 295.37222222222226, 839 | "humidity": 49, 840 | "internetSpeed": 50 841 | }, 842 | { 843 | "name": "Rome", 844 | "country": "IT", 845 | "region": "Europe", 846 | "cost": 3250, 847 | "currency": "USD", 848 | "temp": 297.03888888888895, 849 | "humidity": 88, 850 | "internetSpeed": 10 851 | }, 852 | { 853 | "name": "Copenhagen", 854 | "country": "DK", 855 | "region": "Europe", 856 | "cost": 3514, 857 | "currency": "USD", 858 | "temp": 292.03888888888895, 859 | "humidity": 77, 860 | "internetSpeed": 40 861 | }, 862 | { 863 | "name": "Los Angeles", 864 | "country": "US", 865 | "region": "North America", 866 | "cost": 4178, 867 | "currency": "USD", 868 | "temp": 301.48333333333335, 869 | "humidity": 73, 870 | "internetSpeed": 30 871 | }, 872 | { 873 | "name": "Cape Town", 874 | "country": "ZA", 875 | "region": "Africa", 876 | "cost": 2564, 877 | "currency": "USD", 878 | "temp": 288.7055555555556, 879 | "humidity": 84, 880 | "internetSpeed": 10 881 | }, 882 | { 883 | "name": "Rotterdam", 884 | "country": "NL", 885 | "region": "Europe", 886 | "cost": 3736, 887 | "currency": "USD", 888 | "temp": 293.15000000000003, 889 | "humidity": 63, 890 | "internetSpeed": 50 891 | }, 892 | { 893 | "name": "Oslo", 894 | "country": "NO", 895 | "region": "Europe", 896 | "cost": 4294, 897 | "currency": "USD", 898 | "temp": 293.15000000000003, 899 | "humidity": 59, 900 | "internetSpeed": 30 901 | }, 902 | { 903 | "name": "Columbus", 904 | "country": "US", 905 | "region": "North America", 906 | "cost": 4208, 907 | "currency": "USD", 908 | "temp": 301.48333333333335, 909 | "humidity": 65, 910 | "internetSpeed": 20 911 | }, 912 | { 913 | "name": "Dusseldorf", 914 | "country": "DE", 915 | "region": "Europe", 916 | "cost": 3910, 917 | "currency": "USD", 918 | "temp": 295.9277777777778, 919 | "humidity": 68, 920 | "internetSpeed": 30 921 | }, 922 | { 923 | "name": "Philadelphia", 924 | "country": "US", 925 | "region": "North America", 926 | "cost": 4358, 927 | "currency": "USD", 928 | "temp": 303.15000000000003, 929 | "humidity": 45, 930 | "internetSpeed": 30 931 | }, 932 | { 933 | "name": "Minneapolis", 934 | "country": "US", 935 | "region": "North America", 936 | "cost": 3724, 937 | "currency": "USD", 938 | "temp": 293.15000000000003, 939 | "humidity": 82, 940 | "internetSpeed": 20 941 | }, 942 | { 943 | "name": "New York City", 944 | "country": "US", 945 | "region": "North America", 946 | "cost": 4674, 947 | "currency": "USD", 948 | "temp": 302.03888888888895, 949 | "humidity": 35, 950 | "internetSpeed": 40 951 | }, 952 | { 953 | "name": "Chicago", 954 | "country": "US", 955 | "region": "North America", 956 | "cost": 3911, 957 | "currency": "USD", 958 | "temp": 300.9277777777778, 959 | "humidity": 50, 960 | "internetSpeed": 30 961 | }, 962 | { 963 | "name": "Paris", 964 | "country": "FR", 965 | "region": "Europe", 966 | "cost": 4656, 967 | "currency": "USD", 968 | "temp": 296.48333333333335, 969 | "humidity": 49, 970 | "internetSpeed": 70 971 | }, 972 | { 973 | "name": "Miami", 974 | "country": "US", 975 | "region": "North America", 976 | "cost": 4119, 977 | "currency": "USD", 978 | "temp": 304.2611111111112, 979 | "humidity": 74, 980 | "internetSpeed": 30 981 | }, 982 | { 983 | "name": "San Francisco", 984 | "country": "US", 985 | "region": "North America", 986 | "cost": 4854, 987 | "currency": "USD", 988 | "temp": 295.37222222222226, 989 | "humidity": 82, 990 | "internetSpeed": 30 991 | }, 992 | { 993 | "name": "London", 994 | "country": "UK", 995 | "region": "Europe", 996 | "cost": 4504, 997 | "currency": "USD", 998 | "temp": 295.37222222222226, 999 | "humidity": 60, 1000 | "internetSpeed": 30 1001 | } 1002 | ] 1003 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const R = require('ramda'); 2 | const table = require('text-table'); 3 | const cities = require('./cities.json'); 4 | const percentile = require('./percentile'); 5 | 6 | const KtoC = k => k - 273.15; 7 | const KtoF = k => k * 9 / 5 - 459.67; 8 | 9 | const updateTemperature = R.curry((convertFn, city) => { 10 | const temp = Math.round(convertFn(city.temp)); 11 | return R.merge(city, { temp }); 12 | }); 13 | 14 | // const updatedCities = R.map(updateTemperature(KtoF), cities); 15 | 16 | // console.log(updatedCities); 17 | 18 | const city = cities[0]; 19 | const updatedCity = updateTemperature(KtoF, city); 20 | // console.log(updatedCity); 21 | 22 | const totalCostReducer = (acc, city) => { 23 | const { cost = 0 } = city; 24 | return acc + cost; 25 | } 26 | 27 | const totalCost = R.reduce(totalCostReducer, 0, cities); 28 | const cityCount = R.length(cities); 29 | // console.log(totalCost / cityCount); 30 | 31 | const groupByPropReducer = (acc, city) => { 32 | const { cost = [], internetSpeed = [] } = acc; 33 | return R.merge(acc, { 34 | cost: R.append(city.cost, cost), 35 | internetSpeed: R.append(city.internetSpeed, internetSpeed), 36 | }); 37 | } 38 | 39 | const groupedByProp = R.reduce(groupByPropReducer, {}, cities); 40 | 41 | // console.log(groupedByProp); 42 | 43 | const calcScore = city => { 44 | const { cost = 0, internetSpeed = 0 } = city; 45 | const costPercentile = percentile(groupedByProp.cost, cost); 46 | const internetSpeedPercentile = percentile( 47 | groupedByProp.internetSpeed, 48 | internetSpeed, 49 | ); 50 | const score = 51 | 100 * (1.0 - costPercentile) + 52 | 20 * internetSpeedPercentile; 53 | return R.merge(city, { score }); 54 | } 55 | 56 | // const scoredCities = R.map(calcScore, updatedCities); 57 | 58 | // console.log(scoredCities); 59 | 60 | const filterByWeather = city => { 61 | const { temp = 0, humidity = 0 } = city; 62 | return temp > 68 && temp < 85 && humidity > 30 && humidity < 70; 63 | } 64 | 65 | // const filteredCities = R.filter(filterByWeather, scoredCities); 66 | 67 | // console.log(R.length(filteredCities)); 68 | 69 | // const sortedCities = R.sortWith( 70 | // [R.descend(city => city.score)], 71 | // filteredCities, 72 | // ); 73 | 74 | // console.log(sortedCities); 75 | 76 | // const top10 = R.take(10, sortedCities); 77 | 78 | // console.log(top10); 79 | // console.log(R.length(top10)); 80 | 81 | const cityToArray = city => { 82 | const { name, country, score, cost, temp, internetSpeed } = city; 83 | return [name, country, score, cost, temp, internetSpeed]; 84 | }; 85 | const interestingProps = [ 86 | 'Name', 87 | 'Country', 88 | 'Score', 89 | 'Cost', 90 | 'Temp', 91 | 'Internet', 92 | ]; 93 | 94 | const topCities = R.pipe( 95 | R.map(updateTemperature(KtoF)), 96 | R.filter(filterByWeather), 97 | R.map(calcScore), 98 | R.sortWith([R.descend(city => city.score)]), 99 | R.take(10), 100 | R.map(cityToArray), 101 | R.prepend(interestingProps), 102 | table, 103 | )(cities); 104 | 105 | console.log(topCities); -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ramdatutorial", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ramda": { 8 | "version": "0.25.0", 9 | "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz", 10 | "integrity": "sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ==" 11 | }, 12 | "text-table": { 13 | "version": "0.2.0", 14 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 15 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ramdatutorial", 3 | "version": "1.0.0", 4 | "description": "source files for a ramda tutorial", 5 | "main": "index.js", 6 | "author": "James Moore", 7 | "license": "ISC", 8 | "dependencies": { 9 | "ramda": "^0.25.0", 10 | "text-table": "^0.2.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /percentile.js: -------------------------------------------------------------------------------- 1 | const R = require('ramda'); 2 | module.exports = (array, value) => { 3 | const length = R.length(array); 4 | const eqVal = R.equals(value); 5 | const alen = !R.any(eqVal, array) 6 | ? R.range(0, length + 1) 7 | : R.range(0, length); 8 | const sortedArray = R.sort((a, b) => a - b, array); 9 | const idx = R.map(eqVal, sortedArray); 10 | const alenTrue = R.filter((v, i) => { 11 | return idx[alen.indexOf(v)] === true; 12 | }, alen); 13 | const mean = R.mean(alenTrue); 14 | const percent = mean / length; 15 | return percent; 16 | }; 17 | -------------------------------------------------------------------------------- /values.js: -------------------------------------------------------------------------------- 1 | const PI = 3.14; 2 | 3 | const add = (a, b) => a + b; 4 | 5 | console.log(PI); 6 | 7 | console.log(add); 8 | 9 | console.log(PI === 3.14); 10 | 11 | console.log(add === Math.round, add === add); --------------------------------------------------------------------------------