Custom sorting using orderBy directive of Angular - javascript

Below is the sort criteria from A to Z:
1) special characters
2) numbers
3) alphabet
For example:-
$scope.cards = ["815 BRAZOS ST AUSTIN TX 78701","7745 CHEVY CHASE DR AUSTIN TX 78752","701 BRAZOS ST AUSTIN TX 78701","555 ROUND ROCK WEST DR ROUND ROCK TX 78681","400 W 15TH ST AUSTIN TX 78701"]
Expected result after sorting:-
400 W 15TH ST AUSTIN TX 78701
555 ROUND ROCK WEST DR ROUND ROCK TX 78681
701 BRAZOS ST AUSTIN TX 78701
815 BRAZOS ST AUSTIN TX 78701
7745 CHEVY CHASE DR AUSTIN TX 78752
I want to achieve this using Angular orderBy filter. As in JS custom sort function, we got two arguments and by manipulating that we can return >0, <0 and 0 to achieve custom sort.
My Attempt
<div ng-controller="MyCtrl">
<ul ng-repeat="card in cards | orderBy:myValueFunction">
<li>{{card}}</li>
</ul>
</div>
JS
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.cards = ["815 BRAZOS ST AUSTIN TX 78701","7745 CHEVY CHASE DR AUSTIN TX 78752","701 BRAZOS ST AUSTIN TX 78701","555 ROUND ROCK WEST DR ROUND ROCK TX 78681","400 W 15TH ST AUSTIN TX 78701"]
$scope.myValueFunction = function(card,card1) {
console.log(card);
console.log(card1);
return card;
}
}
JSfiddle link
Thanks

According to documentation your function should return a value, that would be used for sorting using standard comparison operators (<,>,=).
So in your case your function should return an value, that would determine sorting. For your case, you need to put some advanced logic to produce such value.
For simples example (sort by first numbers), you get:
$scope.myValueFunction = function(card) {
return card.split(' ')[0]|0;
}
At least you'll have what you've requested in your small sample, see here: http://jsfiddle.net/zjvsu/529/
UPDATED
If you want to compare two values just like standard javascript sort custom function then you will have to use your own filter which returns sorted array.

Related

Is there a way to calculate distance between two coordinates ON TERRAIN and not as the crow flies?

I am looking for a way to find the distance between two coordinates that have elevation data as well, but I want the solution to take under account the TERRAIN between the two points i.e the shortest way between them on the ground and not "as the crow flies".
I have found and used the Haversine formula for the distance "in the air" but obviously it will not yield the real distance that a man would walk on the ground as in between the two points there might be a slope that goes up and / or down. The larger the distance between the points the bigger the error margin.
I have sampled a real .gpx file and converted its data into JSON format. it looks like this:
let jsonSample = [{
"lat": "57.107297", // 0
"lon": "-5.334734",
"ele": "957.00"
}, // distance between 0 and 1 => 169.1849929515954 m (as the crow flies) elevation difference: 50.210000000000036
{
"lat": "57.106590", // 1
"lon": "-5.332253",
"ele": "1007.21"
}, // distance between 1 and 2 => 162.49601252670058 m (as the crow flies) elevation difference: 23.789999999999964
{
"lat": "57.105537", // 2 (summit)
"lon": "-5.330387",
"ele": "1031.00"
}, // distance between 2 and 3 => 32.45395539826568 m (as the crow flies) elevation difference: -13
{
"lat": "57.105284", // 3
"lon": "-5.330119",
"ele": "1018.00"
}];
Real distances should be longer than the ones calculated with Haversine formula. But how do I calculate it?
Googling "haversine formula elevation" found me this Math.SE question and answer.
Heeding the comments, so long as the distances you're measuring aren't too far apart, using the Pythagorean Theorem, you can add the elevation deltas in.
I'd use Pythagoras: let d the Haversine distance and dh the difference in altitudes, D=sqrt(d**2+dh**2).
Something like
function haversineWithAltitude(lat1, lon1, alt1, lat2, lon2, alt2) {
const groundDistanceInMeters = haversine(lat1, lon1, lat2, lon2);
const elevationDifferenceMeters = Math.abs(alt1 - alt2);
return Math.sqrt(groundDistanceInMeters * groundDistanceInMeters + elevationDifferenceInMeters * elevationDifferenceInMeters);
}
should thus work – but as said, this will inevitably become more inaccurate if the length between the points is very long. (At that point, I'd, not being a mathematician and not knowing better, segment the long leg and calculate each distance piecewise.)

I need help. Seems like a basic tool that I cannot seem to find

Lets say I have some random text info that I have collected from subpar sources. The text consists of something as follows:
1st Floor - aklsl;asndgjasblgkbaskdbfjkabsdlkfbjla 2nd Floor - infoinfofino theoreticalinfo yasddadas 3rd Floor - more random stuff relevant to this floor, no consistency in the data etc.
and I want to put this into a string. So:
var string = "1st Floor - aklsl;asndgjasblgkbaskdbfjkabsdlkfbjla 2nd Floor - infoinfofino theoreticalinfo yasddadas 3rd Floor - more random stuff relevant to this floor, no consistency in the data etc.";
How do I split the string into an array based on the special characters "1st" "2nd" "3rd" "4th" etc. because there is no numerical pattern to the info after each floor.
I was thinking
var newString = string.split("1st" || "2nd" || "3rd");
console.log(newString);
You can use split with regex:
var string = "1st Floor - aklsl;asndgjasblgkbaskdbfjkabsdlkfbjla 2nd Floor - infoinfofino theoreticalinfo yasddadas 3rd Floor - more random stuff relevant to this floor, no consistency in the data etc.";
var result = string.split(/(1st|2nd|3rd)/);
console.log(result);
Maybe you want a regex that could obtain n Floors instead of only some of them (1st, 2nd and 3rd)
var string = "1st Floor - aklsl;asndgjasblgkbaskdbfjkabsdlkfbjla 2nd Floor - infoinfofino theoreticalinfo yasddadas 3rd Floor - more random stuff relevant to this floor, no consistency in the data etc.";
var result = string.split(/[\d]+\w+\sFloor\s[-]\s/).filter(item => item.length > 1);
console.log(result);

Javascript: How to join an array the most efficiently into chunks less than 64 characters?

I have a very long array of names like this:
namelist = [ "Andrew Alexander Brown", "Charlie Christopher Drake", "Edward Elsevier Furlong", "Gareth Gates Harper", "Indiana Chewbacca Jones", "Kevin M Lamarr", "Michael Randy Newman", "Oliver Terry Pratchett", "Queen Liz Regina", "Stuart Townsend", "Umar Vespa", "Woodford X Xanadu", "Yanick Zebra" ];
I would like to extract the names from the list into strings with each name separated by a pipe character (|). Each new string should be smaller than 48 characters, for instance the output should be like this (but less than or equal to 48 characters):
Andrew Alexander Brown|Charlie Christopher Drake|Edward Elsevier Furlong
Gareth Gates Harper|Indiana Chewbacca Jones|Kevin M Lamarr
Michael Randy Newman|Oliver Terry Pratchett|Queen Liz Regina
Stuart Townsend|Umar Vespa|Woodford X Xanadu|Yanick Zebra
I would like the number of new strings to be as small as possible, probably without maintaining the order of the strings in the array - but I am at a loss at how to do this in javascript.
I know I could do something like loop through the namelist and add the next name onto a temporary string. Check the length of this temporary string and output it if it exceeds 48 characters. Keep going around the loop until we have run out of names but this doesn't seem very efficient. For instance if a short name is followed by an extremely long name then characters (which could be filled by another smaller name in the temporary string) will be wasted.
Any pointers at how best to achieve this?
This is what is knows as The Bin Packing Problem
Solutions will depend on your definition of efficient, more efficient bin packing tends to take longer to compute. But less efficient bin packing tends to take much less computational resources (could be deemed more efficient in terms of computational resources).
Here is my solution using ECMA5 specifications, it sacrifices computational resources in favour of more efficient bin packing.
I have chosen to leave the powerSet function a general purpose one, that means it can be reused for other purposes. As #Bergi has highlighted, you may get better efficiency with respect to computational resources if you created a custom function which incorporates the first filter from joinStringsMaxCharacters
Javascript
General Power Set function
function powerSet(array) {
var lastElement,
sets;
if (!array.length) {
sets = [[]];
} else {
lastElement = array.pop();
sets = powerSet(array).reduce(function (previous, element) {
previous.push(element);
element = element.slice();
element.push(lastElement);
previous.push(element);
return previous;
}, []);
}
return sets;
}
Helper functions
function isString(element) {
return typeof element === 'string';
}
function isNotUsed(element) {
return this.every(function (u) {
return u.indexOf(element) === -1;
});
}
function sumLength(s, el) {
return s + el.length;
}
Packing bins with joined strings
function joinStringsMaxCharacters(arrayOfStrings, numberOfCharacters, separator) {
if (!Array.isArray(arrayOfStrings) || !arrayOfStrings.every(isString)) {
throw new TypeError('arrayOfStrings is not an array of strings!');
}
numberOfCharacters = numberOfCharacters >>> 0;
if (!separator || !isString(separator)) {
separator = '|';
}
var arrayLength = arrayOfStrings.length;
return powerSet(arrayOfStrings).filter(function (set) {
return set.length && (set.length === 1 || set.reduce(sumLength, set.length - 1) <= numberOfCharacters);
}).sort(function (a, b) {
return b.reduce(sumLength, b.length) - a.reduce(sumLength, a.length) || b.length - a.length;
}).reduce(function (used, cur) {
if (used.reduce(sumLength, 0) < arrayLength && cur.every(isNotUsed, used)) {
used.push(cur);
}
return used;
}, []).map(function (bin) {
return bin.join(separator);
});
}
Array of strings to be packed into bins
var nameList = [
"Andrew Alexander Brown",
"Charlie Christopher Drake",
"Edward Elsevier Furlong",
"Gareth Gates Harper",
"Indiana Chewbacca Jones",
"Kevin M Lamarr",
"Michael Randy Newman",
"Oliver Terry Pratchett",
"Queen Liz Regina",
"Stuart Townsend",
"Umar Vespa",
"Woodford X Xanadu",
"Yanick Zebra"];
Pack the bins and display the content of each bin
joinStringsMaxCharacters(nameList, 48).forEach(function (bin) {
console.log(bin);
});
Output
Kevin M Lamarr|Stuart Townsend|Woodford X Xanadu
Michael Randy Newman|Queen Liz Regina|Umar Vespa
Charlie Christopher Drake|Oliver Terry Pratchett
Edward Elsevier Furlong|Indiana Chewbacca Jones
Andrew Alexander Brown|Gareth Gates Harper
Yanick Zebra
On jsFiddle
var namelist= ["Andrew Alexander Brown", "Charlie Christopher Drake", "Edward Elsevier Furlong", "Gareth Gates Harper", "Indiana Chewbacca Jones", "Kevin M Lamarr", "Michael Randy Newman", "Oliver Terry Pratchett", "Queen Liz Regina", "Stuart Townsend", "Umar Vespa", "Woodford X Xanadu", "Yanick Zebra"];
var c48= [], next, temp= '', i= 0, L= namelist.length;
while(i<L){
next= namelist[i++];
if((temp+next).length<= 47) temp=temp? temp+'|'+next: next;
else{
c48.push(temp);
temp= next;
}
}
if(next)c48.push(next);
c48.join('\n')
/* returned value: (String)
Andrew Alexander Brown|Charlie Christopher Drake
Edward Elsevier Furlong|Gareth Gates Harper
Indiana Chewbacca Jones|Kevin M Lamarr
Michael Randy Newman|Oliver Terry Pratchett
Queen Liz Regina|Stuart Townsend|Umar Vespa
Yanick Zebra
*/

How to convert this array of strings to array object

I ma having this string returned from my C# code. I need to implement Google Maps. How d i convert this into array.
String
var array = [["Andover - Wyevale Garden Centre","Concession A","Andover Garden Centre","Salisbury Road","Andover","SP11 7DN","01264 710114","14.9 miles","51.1998552","-1.5111393"],
["Portsmouth - Gunwharf Quays","Unit 29","Gunwharf Quays","Portsmouth","Hampshire","PO1 3TZ","02392 819558","20.8 miles","50.7963663","-1.1065603"],
["Chichester","83 North Street","Chichester","West Sussex","PO19 1LQ","01243 380058","25.9 miles","50.837269","-0.77846"],
["Newport - Isle of Wight","117/119 High Street","Newport","Isle of Wight","PO30 1TP","01983 527485","27.1 miles","50.700399","-1.294872"],
["Guildford","20-21 North Street","Guildford","Surrey","GU1 4AF","01483 456978","29.8 miles","51.2369881","-0.5731617"]]
i dont know but when i do array[1][0] it should return "Portsmouth" in chrome console BUT it is coming as undefined.
I suspect array variable is identified as string and not array.
when i do array[0][4] i get "A" as output.
Please help
use this .. this will running on my side .
var array = '[["d","ddd","sadasd","Salisbury Road","Andover","SP11 7DN","01264 710114","14.9 miles","51.1998552","-1.5111393"],["Portsmouth - Gunwharf Quays","Unit 29","Gunwharf Quays","Portsmouth","Hampshire","PO1 3TZ","02392 819558","20.8 miles","50.7963663","-1.1065603"],["Chichester","83 North Street","Chichester","West Sussex","PO19 1LQ","01243 380058","25.9 miles","50.837269","-0.77846"],["Newport - Isle of Wight","117/119 High Street","Newport","Isle of Wight","PO30 1TP","01983 527485","27.1 miles","50.700399","-1.294872"],["Guildford","20-21 North Street","Guildford","Surrey","GU1 4AF","01483 456978","29.8 miles","51.2369881","-0.5731617"]]'
var arrayObj = JSON.parse(array)
console.log(arrayObj)
console.log(arrayObj[1][0])
// returns---
Portsmouth - Gunwharf Quays
OK try this:
var array = [["Andover - Wyevale Garden Centre","Concession A","Andover Garden Centre","Salisbury Road","Andover","SP11 7DN","01264 710114","14.9 miles","51.1998552","-1.5111393"],
["Portsmouth - Gunwharf Quays","Unit 29","Gunwharf Quays","Portsmouth","Hampshire","PO1 3TZ","02392 819558","20.8 miles","50.7963663","-1.1065603"],
["Chichester","83 North Street","Chichester","West Sussex","PO19 1LQ","01243 380058","25.9 miles","50.837269","-0.77846"],
["Newport - Isle of Wight","117/119 High Street","Newport","Isle of Wight","PO30 1TP","01983 527485","27.1 miles","50.700399","-1.294872"],
["Guildford","20-21 North Street","Guildford","Surrey","GU1 4AF","01483 456978","29.8 miles","51.2369881","-0.5731617"]];
Try removing your encompassing double quotes and include a terminating semi-colon ;...
var array = [["Andover - Wyevale Garden Centre","Concession A","Andover Garden Centre","Salisbury Road","Andover","SP11 7DN","01264 710114","14.9 miles","51.1998552","-1.5111393"],
["Portsmouth - Gunwharf Quays","Unit 29","Gunwharf Quays","Portsmouth","Hampshire","PO1 3TZ","02392 819558","20.8 miles","50.7963663","-1.1065603"],
["Chichester","83 North Street","Chichester","West Sussex","PO19 1LQ","01243 380058","25.9 miles","50.837269","-0.77846"],
["Newport - Isle of Wight","117/119 High Street","Newport","Isle of Wight","PO30 1TP","01983 527485","27.1 miles","50.700399","-1.294872"],
["Guildford","20-21 North Street","Guildford","Surrey","GU1 4AF","01483 456978","29.8 miles","51.2369881","-0.5731617"]];

Why does esri.geometry.getLength work wrong?

The function http://help.arcgis.com/en/webapi/javascript/arcgis/jsapi/#namespace_geometry/esri.geometry.getLength should calculate distances between points.
When I am trying to calculate distance between points having 100 meters between them
p1=new esri.geometry.Point(3997030.6690969253, 7444299.320646087, new esri.SpatialReference({ wkid: 102113 }));
Object
p2=new esri.geometry.Point(3996951.455397143, 7444142.154020177, new esri.SpatialReference({ wkid: 102113 }));
Object
esri.geometry.getLength(p1, p2)
176.00045037719127
I am getting 176 which is wrong. Projection is Web Mercator (WKID 102113).
It looks like it's just calculating the simple euclidean map distance between the two points (3997030,7444299) and (3996951, 7444142).
a^2 + b^2 = c^2
where a = (3997031 - 3996951) and b = (7444299 - 7444142)
c = 176
So 176 is the map distance, what you want is the real world ground distance. You'll probably have to use a GeometryService to accomplish this, I don't think the Javascript can do it on it's own. Here's ESRI's sample of it: https://developers.arcgis.com/javascript/jssamples/util_distance.html

Categories

Resources