Sort Array in special manner - javascript

I have a problem sorting an array. I am not the smartest concerning these sort algorithms.
The array should have following structure:
var arr = [
[week, IssuesPriority1, IssuesPriority2, IssuesPriority3],
[week, IssuesPriority1, IssuesPriority2, IssuesPriority3],
[week, IssuesPriority1, IssuesPriority2, IssuesPriority3],
...
];
So for each week there is a number of issues for the priority very high, high, medium.
The string that needs to be parsed in this structure is following:
var string =
"26|3|1,27|6|1,28|7|1,29|2|1,30|2|1,31|2|1,32|2|1,33|3|1,
35|1|1,34|2|1,36|0|1,37|0|1,38|1|1,26|11|2,27|10|2,28|9|2,
29|13|2,30|10|2,31|8|2,32|10|2,33|12|2,34|14|2,35|11|2,
36|11|2,37|12|2,38|14|2,27|17|3,26|13|3,29|26|3,28|21|3,30|25|3,
31|20|3,34|30|3,32|18|3,33|25|3,35|33|3,36|28|3,38|28|3,37|27|3";
var arr = string.split(",");
for(var i = 0; i < arr.length; i++){
var currentArr = arr[i].split("|");
var week = currentArr[0];
var issues = currentArr[1];
var priority = currentArr[2];
}
I have a lack of ideas sorting it in the desired way. Can you help me?

I don't think you want any sorting at all. You are looking for grouping!
var arr = string.split(",");
var weeks = {};
for (var i = 0; i < arr.length; i++) {
var currentArr = arr[i].split("|");
var week = currentArr[0];
var issue = currentArr[1];
var priority = currentArr[2];
if (!(week in weeks))
weeks[week] = {1:[], 2:[], 3:[]};
// if the number of issues levels were unknown,
// you'd start with an empty object instead
// and create the arrays dynamically in a manner similar to the weeks
weeks[week][priority].push(issue);
}
return Object.keys(weeks).map(function(week) {
return [week, weeks[week][1], weeks[week][2], weeks[week][3]];
});
(to get the result ordered by week number, add a sort(function(a,b){return a-b}) before the .map() call)

In your situation I would recommand to put the values in the array first. In the second step I would sort the array using the sort method.
function getSortedArrayByString(myString) {
var arraySplittedString, i, tmpValueArray, tmpInnerArray, resultingArray;
arraySplittedString = myString.split(",");
resultingArray = [];
for(i = 0; i < arraySplittedString.length; i++){
// tmpArray has the format of [<week>, <IssuesPriority1>, <IssuesPriority2>]
tmpValueArray = arraySplittedString[i].split("|");
// Push it in the new array.
resultingArray.push(tmpValueArray);
}
// Sort array by weeks ascending.
resultingArray.sort( function (a, b) {
return a[0] - b[0];
});
return resultingArray;
}
Running fiddle.
If you also want to sort by the count of issues, you simply can customize the inner sort function.
With this solution all values are saved as strings. You can convert them by using the parseInt function.

Related

Compare 2 different Arrays by ID and calculate difference

I got 2 arrays
ArrayA = {"data":{"PlayerList":[{"Platform":1,"PlayerExternalId":205288,"Price":250,"RemainingTime":22},{"Platform":1,"PlayerExternalId":205753,"Price":10000,"RemainingTime":22}]}}
ArrayB = {"datafut": [{"currentPricePs4": "4149000","currentPriceXbox": "3328000","PlayerExternalId": "151152967"},{"currentPricePs4": "3315000","currentPriceXbox": "2720000","PlayerExternalId": "151198320"}]}
ArrayB is like a small database to compare prices. ArrayA needs theoretically an Interception with ArrayB. But this creates a new ArrayC which is complicated for me because I need the index of the results from ArrayA.
Moreover when comparing both array IDs, I need to compare both prices and calculate a difference into a variable so I can work with it later. How can I achieve this?
This is my pseudo code. Idk if this is even the right way..
Filter ArrayB by ArrayA //by playerID
for(
NewPrice = ArrayA.price / ArrayB.price + Index of ArrayA.price
index = Index of ArrayA.price)
Edit: or could I append the price from arrayB to arrayA and can calculate then somehow?
You can pass both arrays to following function: I have stored index, now if you only need index, you don't need to sort it otherwise I am sorting it on the base of index to keep the original order.
function mergeArrays(arrayA, arrayB) {
var players = arrayA.data.PlayerList;
var data = arrayB.data;
var arrayC = [];
for(let i=0; i<data.length; i++) {
var playerId = data[i].PlayerExternalId;
for(let j=0; j<players.length; j++) {
if(players[j].PlayerExternalId != playerId) {
continue;
}
var obj = {};
obj.playerId = playerId;
obj.index = j;
obj.price = players[j].price;
obj.xboxprice = data[i].currentPriceXbox;
obj.ps4price = data[i].currentPricePs4;
arrayC.push(obj);
}
}
arrayC.sort((a,b) => (a.index < b.index)?-1:(a.index>b.index?1:0));
return arrayC;
}

Create ranges of dates from a single array of dates

How can I make ranges of dates (from the newest to the oldest) from one array of dates?
I have this array of dates:
["2017-11-16T12:12:50.323Z", "2017-11-15T16:13:24.219Z", "2017-11-14T16:13:55.449Z", "2017-11-13T06:56:21.332Z"]
And I want to have the following ranges of dates result:
["2017-11-16T12:12:50.323Z", "2017-11-15T16:13:24.219Z"]
["2017-11-15T16:13:24.219Z", "2017-11-14T16:13:55.449Z"]
["2017-11-14T16:13:55.449Z", "2017-11-13T06:56:21.332Z"]
I want to achieve this in JavaScript
Assuming that the dates are ordered, you can iterate with for loop up to the last item, and Array#slice each pair:
var dates = ["2017-11-16T12:12:50.323Z", "2017-11-15T16:13:24.219Z", "2017-11-14T16:13:55.449Z", "2017-11-13T06:56:21.332Z"];
var ranges = [];
for(var i = 0; i < dates.length - 1; i++) {
ranges.push(dates.slice(i, i + 2));
}
console.log(ranges);
You could take the actual element of the array and the next for a new item of the result with a Array#reduce pattern which returns the next item for the next loop as actual item.
var data = ["2017-11-16T12:12:50.323Z", "2017-11-15T16:13:24.219Z", "2017-11-14T16:13:55.449Z", "2017-11-13T06:56:21.332Z"],
result = [];
data.sort((a, b) => b > a || -(b < a)); // desc
data.reduce((a, b) => (result.push([a, b]), b));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var data = ["2017-11-16T12:12:50.323Z", "2017-11-15T16:13:24.219Z", "2017-11-14T16:13:55.449Z", "2017-11-13T06:56:21.332Z"];
var paired = data.sort().slice(0, -1).map(function(d, i) {
return [d, data[i+1]];
})
console.log(paired);
Or using es6 you could do it in one line:
let data = ["2017-11-16T12:12:50.323Z", "2017-11-15T16:13:24.219Z", "2017-11-14T16:13:55.449Z", "2017-11-13T06:56:21.332Z"];
let paired = data.sort().slice(0, -1).map((d, i) => [d, data[i+1]])
console.log(paired)
Since you don't need any advanced sorting, you can just use the default .sort() function which javascript provides.
var datesSorted = dates.sort();
Splitting into pairs can be done in a cycle, because JavaScript doesn't provide any direct "split array into pairs" function.
The final script should look something like this:
var dates = ["2017-11-16T12:12:50.323Z", "2017-11-15T16:13:24.219Z", "2017-11-14T16:13:55.449Z", "2017-11-13T06:56:21.332Z"];
var datesSorted = dates.sort();
var datePairs = function(datesSorted) {
var pairs = [];
for (var i=0 ; i<datesSorted.length ; i+=2) { //iterate by two
if (datesSorted[i+1] !== undefined) { //check if a date has a "pair"
pairs.push ([datesSorted[i], datesSorted[i+1]]); //if it does, push them both
} else {
pairs.push ([datesSorted[i]]);
}
}
return pairs;
};
You're array of date arrays should now be stored in datePairs.

Javascript - nested loops and indexes

I am trying to build an array that should look like this :
[
[{"name":"Mercury","index":0}],
[{"name":"Mercury","index":1},{"name":"Venus","index":1}],
[{"name":"Mercury","index":2},{"name":"Venus","index":2},{"name":"Earth","index":2}],
...
]
Each element is the concatenation of the previous and a new object, and all the indexes get updated to the latest value (e.g. Mercury's index is 0, then 1, etc.).
I have tried to build this array using the following code :
var b = [];
var buffer = [];
var names = ["Mercury","Venus","Earth"]
for (k=0;k<3;k++){
// This array is necessary because with real data there are multiple elements for each k
var a = [{"name":names[k],"index":0}];
buffer = buffer.concat(a);
// This is where the index of all the elements currently in the
// buffer (should) get(s) updated to the current k
for (n=0;n<buffer.length;n++){
buffer[n].index = k;
}
// Add the buffer to the final array
b.push(buffer);
}
console.log(b);
The final array (b) printed out to the console has the right number of objects in each element, but all the indexes everywhere are equal to the last value of k (2).
I don't understand why this is happening, and don't know how to fix it.
This is happening because every object in the inner array is actually the exact same object as the one stored in the previous outer array's entries - you're only storing references to the object, not copies. When you update the index in the object you're updating it everywhere.
To resolve this, you need to create new objects in each inner iteration, or use an object copying function such as ES6's Object.assign, jQuery's $.extend or Underscore's _.clone.
Here's a version that uses the first approach, and also uses two nested .map calls to produce both the inner (variable length) arrays and the outer array:
var names = ["Mercury","Venus","Earth"];
var b = names.map(function(_, index, a) {
return a.slice(0, index + 1).map(function(name) {
return {name: name, index: index};
});
});
or in ES6:
var names = ["Mercury","Venus","Earth"];
var b = names.map((_, index, a) => a.slice(0, index + 1).map(name => ({name, index})));
Try this:
var names = ["Mercury","Venus","Earth"];
var result = [];
for (var i=0; i<names.length; i++){
var _temp = [];
for(var j=0; j<=i; j++){
_temp.push({
name: names[j],
index:i
});
}
result.push(_temp);
}
console.log(result)
try this simple script:
var b = [];
var names = ["Mercury","Venus","Earth"];
for(var pos = 0; pos < names.length; pos++) {
var current = [];
for(var x = 0; x < pos+1; x++) {
current.push({"name": names[x], "index": pos});
}
b.push(current);
}

How to dynamically slice Array in Javascript

I have a month array in javascript, for example:
2012/09/01,2012/10/01,2012/11/01,2012/12/01,2013/01/01,2013/02/01,2013/03/01,
2012/09/01,2012/10/01,2012/11/01,2012/12/01,2013/01/01,2013/02/01,2013/03/01,2013/04/01,
2012/09/01,2012/10/01,2012/11/01,2012/12/01
What I wanna separate the Array is that:
if (monthArray[i] > monthArray[i + 1])
// slice the Array.
So, for the above example, I should get 3 new Arrays. They are:
Array1: 2012/09/01,2012/10/01,2012/11/01,2012/12/01,2013/01/01,2013/02/01,2013/03/01
Array2: 2012/09/01,2012/10/01,2012/11/01,2012/12/01,2013/01/01,2013/02/01,2013/03/01,2013/04/01
Array3:2012/09/01,2012/10/01,2012/11/01,2012/12/01
I know it is easy to do it if we know specific length, my question is, how to do it if we dynamically get a month Array(it may be divided into n groups). How to do that? Thanks!
I don't know of any better way than to iterate over the array to build your slices:
var arr = ['2012/09/01','2012/10/01','2012/11/01','2012/12/01','2013/01/01','2013/02/01','2013/03/01','2012/09/01','2012/10/01','2012/11/01','2012/12/01','2013/01/01','2013/02/01','2013/03/01','2013/04/01','2012/09/01','2012/10/01','2012/11/01','2012/12/01'];
var slices = [];
var start = 0;
for (var i=0; i<arr.length; i++) {
if (check(arr, i)) {
slices.push(arr.slice(start, i+1));
start = i+1;
}
}
function check(array, index) {
if (index+1 === array.length) return true;
return Date.parse(array[index]) > Date.parse(array[index+1]);
}
This solution has the advantage that it doesn't build the slices one element at a time, instead it builds them one slice at a time.
Assuming you want an array-of-arrays as a result, you can do this with .reduce:
var partitions = dateList.reduce(function(rv, month) {
var partition = rv[rv.length - 1], prevMonth = partition[partition.length - 1];
if (!prevMonth || prevMonth < month)
partition.push(month);
else
rv.push([month]);
return rv;
}, [ [] ]);
Starting from a list of partitions with one (empty) partition, this just checks the last month in the last partition to see if it's smaller than the current month under examination. If so (or if we're on the very first one), we add the month onto the partition. If not, then a new partition is started, containing just the current month.
So assuming you want to end up with an array of arrays, then just do it with a for loop...
var result = []; //this will contain multiple arrays once finished
var currentArray = [];
for (var i = 0; i < monthArray.length; i++) {
currentArray.push(monthArray[i]);
if (i < monthArray.length - 1 && monthArray[i] > monthArray[i + 1]) {
result.push(currentArray);
currentArray = [];
}
}
result.push(currentArray);
//result[0] is Array1
//result[1] is Array2
//result[2] is Array3
Here is a working example

Sorting an array by another index array

I'm iterating over array couples and I need to sort one by the order of the other.
Say I have these two arrays:
aLinks = [4,5,6]
bLinks = [1,2,3,4,5,6]
I need to return:
aLinks = [4,5,6]
bLinks = [4,5,6,1,2,3]
meaning that i need to have the items that match first array first and than the rest,
sorted by order if possible.
I'm working with d3 so I'm using forEach to go through the link sets and save the order of aLinks.
I don't know how to apply this order to bLinks
var linkOrder = [];
linkSets.forEach(function(set, i) {
linkOrder = [];
set.aLinks.forEach(function(link,i){
linkOrder.push(link.path);
})
});
You can do it like:
Take out the matching items from second array into a temp array
Sort the temp array
Sort the second array containing only items that did not match
Concatenate the second array into the temp array
Code - With the fix provided by User: basilikum
var first = [4,5,6];
var second = [1,7,3,4,6,5,6];
var temp = [], i = 0, p = -1;
// numerical comparator
function compare(a, b) { return a - b; }
// take out matching items from second array into a temp array
for(i=0; i<first.length; i++) {
while ((p = second.indexOf(first[i])) !== -1) {
temp.push(first[i]);
second.splice(p, 1);
}
}
// sort both arrays
temp.sort(compare);
second.sort(compare);
// concat
temp = temp.concat(second);
console.log(temp);
Working Demo: http://jsfiddle.net/kHhFQ/
You end up with A + sort(A-B) - so you just need to compute the difference between the 2 arrays. Using some underscore convenience methods for example:
var A = [4,5,6];
var B = [1,2,3,4,5,6];
var diff = _.difference(A,B);
var result = _.flattern(A, diff.sort());
iterate the first array, removing the values from the second array and then appending them to the start of the array to get the right order :
var arr1 = [4,5,6];
var arr2 = [1,2,3,4,6,5];
arr1.sort(function(a,b) {return a-b;});
for (i=arr1.length; i--;) {
arr2.splice(arr2.indexOf(arr1[i]), 1);
arr2.unshift( arr1[i] );
}
FIDDLE

Categories

Resources