How do I sort a concatenated array in JavaScript? - javascript

My code:
var company=new Array("Kestrel Moon:","BB:");
var basicPri=new Array(1165,1231);
for(var i=0;i<15;i++){
var companyTotal=company[i].concat(basicPri[…
document.write(""+companyTotal+"")
It shows on the screen:
Kestrel Moon: 1165
BB: 1231
I want to sort the array so that it goes ascending order of highest value of price so it should display it as:
BB: 1231
Kestrel Moon: 1165
A normal sort would not do it as it would sort the prices but the company names stay where they are, how do I sort both arrays so it would display what I want to display?
Thank You

typically, you would group the name with number:
function sortNumber(a,b)
{
return b[1] - a[1]; // comparing using 2nd element
}
var n = [["ccc", 10.23], ["www", 23.12], ["mmm", 0.56]];
document.write(n.sort(sortNumber));
output:
www,23.12,ccc,10.23,mmm,0.56
and if you use jQuery, you can create a table from the result:
function sortNumber(a,b)
{
return b[1] - a[1]; // comparing using 2nd element
}
var n = [["ccc", 10.23], ["www", 23.12], ["mmm", 0.56]];
sorted = n.sort(sortNumber);
$('body').append('<table id="thetable"></table>');
$('#thetable').css({borderCollapse: 'collapse'})
for (i = 0; i < sorted.length; i++) {
$('#thetable').append('<tr><td>' + sorted[i][0] + '</td><td>' + sorted[i][1] + '</td></tr>')
}
$('td').css({ border: '1px solid #ccc', padding: '0.2em 1em' });

Here's a possibility using your code as base (i.e. 2 arrays):
// comparaison functor
function sorter(a, b) {
return a.name.localeCompare(b.name);
}
// build a sorted array of object like
// [ { "name": "foo", price: 123 }, ... ]
// sorted by company name (Locale aware order)
function mysort(comp, prices) {
var res = [];
for (var i = 0; i < comp.length; i++) {
res.push({"name": comp[i], "price": prices[i]});
}
return res.sort(sorter);
}
var company = ["Kestrel Moon:", "BB:"];
var basicPri = [1165, 1231];
var companyTotal = "";
var arr = mysort(company, basicPri);
for (var i in arr) {
companyTotal += arr[i].name + " " + arr[i].price + "<br/>";
}
document.write(companyTotal);
Tested on chrome 6.0.427.0 dev

A normal sort would not do it as it would sort the prices but the company names stay where they are ...
In this case, an array of objects would probably be a better data structure for your data. Consider the example below:
var dict = [
{company: 'Kestrel Moon:', basicPri: '1165'},
{company: 'BB:', basicPri: '1231'}
];
var sorted = dict.sort(function(a, b) {
return a.company.localeCompare(b.company);
});
console.log(sorted[0].company + ' ' + sorted[0].basicPri);
console.log(sorted[1].company + ' ' + sorted[1].basicPri);
// Prints:
// ------------------
// BB: 1231
// Kestrel Moon: 1165

Related

Sort a 2D Array/Grid/Table of items in Javascript

I have an inventory of items in my game and the player will need to have the ability to auto-sort the items based on several criteria being name,quantity and type.
// create the Inventory grid
var InventoryWidth = 2;
var InventoryHeight = 4;
var Inventory = new Array(InventoryWidth);
for (var i = 0; i < InventoryWidth; i++) {
Inventory[i] = new Array(InventoryHeight);
}
// set the Items & default quantities
Inventory[0][0] = "Potion";
Inventory[1][0] = 2;
Inventory[0][1] = "Elixir";
Inventory[1][1] = 9;
Inventory[0][2] = "Antidote";
Inventory[1][2] = 5;
Inventory[0][3] = "Ether";
Inventory[1][3] = 1;
// function for sorting items
function Sort2D(array2D, byColumn, ascending) {
// sort, seems I am using the wrong sorting function or my approach is wrong here:
// not sure how to do ASC/DESC as well
array2D.sort(function(a, b)
{
if(a[0] === b[0])
{
var x = a[byColumn].toLowerCase(), y = b[byColumn].toLowerCase();
return x < y ? -1 : x > y ? 1 : 0;
}
return a[0] - b[0];
});
}
// sort all rows by first column: "name", setting to 1 should compare and sort the quantities instead
Sort2D( Inventory, 0, true);
// print grid contents
var output = "";
for(var i = 0; i < InventoryHeight; i++) {
if (i == 0) {
output += " | name | own |";
}
for(var j = 0; j < InventoryWidth; j++) {
if (j == 0) {
output += "\n"+i+"|";
}
output+=Inventory[j][i];
if (j >= Inventory[0].length-1) {
output += "|\n";
} else {
output += ", ";
}
}
}
console.log(output);
However I can't seem to figure out how to sort the grid like a table of items.
I'd need it to sort the row order by a chosen column and the ability to have it in ASC/DESC order. How would I go about this?
To sort an array alphabetically, you just need to use the localeCompare method. Numbers have their own version and that can be confusing, so we coerce the variable before comparing it.
function sortAlphabetically(a, b) {
return String(a).localeCompare(b);
}
["cat", "apple", "dog", "beef"].sort(sortAlphabetically);
// -> ["apple", "beef", "cat", "dog"]
I think the main problem you're having is actually with the way you've created your array. At the moment, your array looks like this:
var inventory = [
["Potion", "Elixir", "Antidote", "Ether"],
[2, 9, 5, 1]
];
That means there's no association between "Potion" and 2, other than the array indicies. I think you'll have much better luck if you adjust the array to look like this.
var inventory = [
["Potion", 2],
["Elixir", 9],
["Antidote", 5],
["Ether", 1]
];
Sorting that is much easier. As a bonus, running the .concat() method will clone the array before trying to sort it so the original data isn't modified and having the function return the data in ascending order by default is more conventional.
function sort2D(array, byColumn, isDescending) {
var sorted = array.concat().sort(function (a, b) {
return typeof a[byColumn] === "string"
? sortAlphabetically(a[byColumn], b[byColumn])
: a[byColumn] - b[byColumn];
});
return isDescending
? sorted.reverse()
: sorted;
}
sort2D(inventory, 0);
// -> [ ["Antidote", 5], ["Elixir", 9], ["Ether", 1], ["Potion", 2] ]
sort2D(inventory, 0, true);
// -> [ ["Potion", 2], ["Ether", 1], ["Elixir", 9], ["Antidote", 5] ]
sort2D(inventory, 1);
// -> [ ["Ether", 1], ["Potion", 2], ["Antidote", 5], ["Elixir", 9] ]
I hope that helps.
Update:
Logging out your information becomes easier as well:
var output = inventory
.map(function (inv) {
return "| " + inv.join(" | ") + " |";
})
.join("\n");
console.log("| name | own |\n" + output);
Update 2:
Here's how to sort the old data.
function sort2D(array, byColumn, isDescending) {
// Step 1: sort the part of the array you're trying to sort.
var preSort = array[byColumn].concat().sort(function (a, b) {
return typeof a === "string"
? sortAlphabetically(a, b)
: a - b;
});
if (isDescending) {
preSort = preSort.reverse();
}
// Step 2: create a new, sorted array with your sorted column.
var sorted = [];
sorted[byColumn] = preSort;
// Step 3: create a map to show how the array way sorted.
var sortMap = {};
preSort.forEach(function (item, i) {
sortMap[array[byColumn].indexOf(item)] = i;
});
// Step 4: manually sort the other items of the array.
array.forEach(function (info, i) {
var copy = [];
if (i !== byColumn) {
info.forEach(function (item, j) {
copy[sortMap[j]] = item;
});
sorted[i] = copy;
}
});
// Step 5: return the newly sorted array.
return sorted;
}

word combination in an array using javascript

Let's says I've an array['Alex', 'Sam', 'Robert']
I'd like to combine them something like:
Take first array[0] and append with array[2] which will be AlexRobert
first letter of array[0] which is A and append with array[2] that is Robert which will be ARobert
Take array[0] which is Alex and append with first letter of array[2] that is R which will be AlexR
Take first array[0] append with first letter of array[1] along with array[2] which will become AlexSRobert.
Basically the whole idea is when someone enter first name, middle name & last name I should be able to make combination and guess email ids. For example- Juan F. Nathaniel the array form will be like ['Juan', 'F', 'Nathaniel']
I want the combination of first, middle and last name like jaunn, jnathaniel, jaunfnathaniel
I'm beginner and here is what I've written:
var nameCombination = function(name){
var counting = name.split(" ");
for (var i=0; i<counting.length; i++){
console.log(counting[i] + counting[i+1]);
console.log(counting[i].split("",1) + counting[i+1]);
}
}
nameCombination('Alex Sam Robert');
I'm assuming you needed a function to do this? Here is a function to handle grabbing pieces of each index of the array. I'll leave it up to you to figure out what type of data you need...
var test = function() {
var array = ['Alex', 'Sam', 'Robert'];
var conditions = [{
index: 0,
length: array[0].length
},
{
index: 1,
length: 1
},
{
index: 2,
length: array[2].length
}]
alert(combine(array, conditions));
}
var combine = function(array, conditions) {
var output = "";
for(index in conditions) {
var condition = conditions[index];
var index = condition['index'];
var length = condition['length'];
output += array[index].substring(0, length);
}
return output;
}
test();
You could use an iterative and recursive approach for variable length of parts an their length.
function combine(array) {
function c(part, index) {
array[index].forEach(function (a) {
var p = part.concat(a);
if (p.length === array.length) {
r.push(p.join(''));
return;
}
c(p, index + 1);
});
}
var r = [];
c([], 0);
return r;
}
var input= ['Johann', 'Sebastian', 'Bach'],
array = input.map(function (a) { return ['', a[0], a]; });
result = combine(array);
console.log(result);
This problem can be solved using recursive approach.
var combinations = function(names, i, n){
if(i == n){
return [];
}
last_names = combinations(names, i + 1, n);
name_combinations = last_names.map(function(last_name){
return [
last_name,
names[i] + last_name,
names[i] + last_name[0],
names[i][0] + last_name,
names[i][0] + last_name[0]
]
});
name_combinations = [].concat.apply([], name_combinations);
name_combinations.push(names[i]);
return name_combinations;
};
var nameCombinations = function(name){
var name_array = name.split(' ');
return Array.from(new Set(combinations(name_array, 0, name_array.length)));
};
nameCombinations('first last');
above function can generate all the desired combinations for a given name.
for example: nameCombinations('first last') will return ["last", "firstlast", "firstl", "flast", "fl", "first"].
Ok without writing out every combination I will do the first few to give you the idea:
assuming
array[0] is the person's first name
array[1] is the person's middle name
array[2] is the person's last name
Firstname+Lastname:
var output = array[0] + array [2];
Firstname+Middlename:
var output1 = array[0] + array[1];
then then you could display the output using innerHTML:
Javascript:
document.getElementById("output").innerHTML = output + '<br>' + output1;
HTML:
<div id="output"></div>
Keep in mind you would need to keep doing that for the rest of the combinations.
Now for the combinations where you need to get the first letter of the variable you need to use charAt which I found from this stack overflow answer.
You would do the same thing as before, except instead you need to use charAt and do something like so:
Firstname+FirstLetterOfLastName:
var output2 = array[0] + array[2].charAt(0);
And you can output it using the same method as before.
If your still confused leave a comment and I will try and answer your questions.

Multiple data in array but only sort by name

I have an array currently only with names because I cannot figure out how to add more information but not make the script sort that data. For every entry in the array I wish to add a number between 1-20 for each, and also a count of how many is named that name. So it would something like 1. Nielsen (100,000). It's only a problem with my second function because I need to sort it by length.
<script>
var arr = []
arr[0] = " Nielsen"
arr[1] = " Jensen"
arr[2] = " Hansen"
arr[3] = " Pedersen"
arr[4] = " Andersen"
arr[5] = " Christensen"
arr[6] = " Larsen"
arr[7] = " Sørensen"
arr[8] = " Rasmussen"
arr[9] = " Jørgensen"
arr[10] = " Petersen"
arr[11] = " Madsen"
arr[12] = " Kristensen"
arr[13] = " Olsen"
arr[14] = " Thomsen"
arr[15] = " Christiansen"
arr[16] = " Poulsen"
arr[17] = " Johansen"
arr[18] = " Møller"
arr[19] = " Mortensen"
document.getElementById("liste").innerHTML = arr; // Skriver den oprindelige rækkefølge
function Sorter1() {
arr.sort(); // Sorter efter aflabetisk rækkefølge
document.getElementById("liste").innerHTML = arr; // Skriver rækkefølgen
}
function Sorter2() {
arr.sort(function (a, b) {
return b.length - a.length || // sorter efter længde
a.localeCompare(b); // Sorter efter aflabetisk rækkefølge
});
document.getElementById("liste").innerHTML = arr; // Skriver rækkefølgen
}
</script>
If I understand you correct you would like to create a multidimensional array and then sort it on the name alphabetically and on character count. If that is correct I would suggest you to create an multidimensional object with the data needed. Then you will be able to sort on the name key and preserve the other information correctly.
Check this out, it may get you in the right direction
var arr = [
{
name: 'Nielsen',
num: 1,
count: 100
},
{
name: 'Jensenlongest',
num: 15,
count: 230
},
{
name: 'Jensenlong',
num: 13,
count: 500
},
{
name: 'Jensen',
num: 2,
count: 300
},
{
name: 'Hansen',
num: 5,
count: 400
}
]
// Just adds the unsorted arr to the list for demo purpose
updateList(arr)
// On "Sort by length" button click
document.getElementById('sort-by-length').addEventListener('click', function (event) {
arr.sort(sortNameByLength);
updateList(arr);
})
// On "Sort alphabetically" button click
document.getElementById('sort-alphabetically').addEventListener('click', function (event) {
arr.sort(sortNameAlphabetically);
updateList(arr);
})
// Sort by name alphabetically
function sortNameAlphabetically(a, b) {
return a.name > b.name
}
// Sort by name length
function sortNameByLength(a, b) {
return a.name.length - b.name.length
}
// Updates the list according to the current sorting of the arr
function updateList(names) {
var listHtml = ''
names.forEach(function (item, index) {
listHtml += item.name + ', ' + item.num + ' (' + item.count + ')<br>'
})
document.getElementById("liste").innerHTML = listHtml
}
https://jsfiddle.net/sbe8yzv0/4/
This will result in a list like this.
Hansen, 5 (400)
Jensen, 2 (300)
Jensenlong, 13 (500)
Jensenlongest, 15 (230)
Nielsen, 1 (100)
You can use an array of complex objects with the data structure you like (just be consistent). Then define your own sort() method that will compare only the name parameter of your objects. Here's a simple example:
var arr = [];
arr[0] = {ID: 1, Name: "Nielsen", Value: "100"};
arr[0] = {ID: 2, Name: "Jensen", Value: "200"};
// Sort based on the second column, 'Name'.
function sortByName(){
arr.sort(
function(x, y){
return x.Name > y.Name; // Compare and sort based on the 'Name' column only.
}
);
console.log(arr[0]); // If results are correct this is 'Jensen'.
console.log(arr[1]); // If results are correct this is 'Nielsen'.
}
Adapt this to your needs (add the proper columns and data, add the proper variables, make it so that it shows in your page's HTML) and it will do what you want.

Store count of integers in order using javascript

I have string like the following:
11222233344444445666
What I would like to do is output the number followed the times it was displayed:
112433475163
Question is, I want this to be efficient. I can store this in an object as the following:
1: { id: 1, displayed: 2},
2: { id: 2, displayed: 1},
3: { id: 3, displayed: 2},
etc.
I can access this object and increment displayed.
My issues is, there is no guarantee in the order. I would like to store the keys in the order they are in the string. How do I accomplish the importance of the order in the object?
This is a proposal for run length coding with an array which holds infomation about one charcter and the count of it:
{
"char": "1",
"count": 2
},
var string = "11222233344444445666",
array = function () {
var r = [], o = {};
string.split('').forEach(function (a, i, aa) {
if (a !== aa[i - 1]) {
o[a] = { char: a, count: 0 };
r.push(o[a]);
}
o[a].count++;
});
return r;
}(string);
document.write('<pre>' + JSON.stringify(array, 0, 4) + '</pre>');
Quick solution with for loop:
var str = "7771122229933344444445666",
obj = {},
len = str.length,
val = null,
count_str = "",
key = "";
for (var i = 0; i < len; i++) {
val = str[i], key = 'k' + val;
if (!obj[key]) {
obj[key] = {'id': val, 'displayed': 1};
} else {
obj[key].displayed++;
}
}
for (var p in obj) {
count_str += obj[p]['id'] + obj[p]['displayed'];
}
console.log(count_str); // "7312249233475163"
because you have such a small set of distinct numbers, I seen no reason why you can't use a array (yeah it's not super ideal memorywise if you skip values and it becomes sparse, but for such a small subset it won't affect you enough to worry of it). Then you can use (number-1) as the index and increment that number as needed.
var counts = [];
var str = "11222233344444445666";
for(var i in str){
var index = parseInt(str[i])-1
counts[index] = (counts[index]||0)+1;
}
for(var i in counts){
var which = 1+parseInt(i);
var count = counts[i];
console.log("# of " + which +"'s: "+count);
}
https://jsfiddle.net/ga0fqpqn/
note: You shouldn't need the parseInt(i)... just +i should work but I think jsfiddle has a bug with it about it defaulting i to handle like a string.
You could store an additional array with the order of the numbers, which you only append to if the object doesn't yet contain the given number. Then once you're done counting, iterate through that array and output the number and the count from the lookup dictionary.
var chars = "1234576123452345".split("");
var order = [];
var hash = {};
chars.forEach(function(char) {
if (!hash[char]) {
hash[char] = 1;
order.push(char);
} else {
hash[char]++;
}
});
console.log(order.map(function(char) {
return char + hash[char];
}).join(""));
// "12233343537161"

Loop through values in arrays in an array. Output all combinations

I have an object. I want to loop through one of it's properties: itself an array of arrays which contain values. For every one of those values, I want to output an array containing a representative value from each of the child arrays, such that every possible combination of values will be output. Where there are more than one value in a child array, a max of 1 value at a time should be allowed. It's at this point that I think it should 'jump on' to the next one (and do the same for all others) but I'm not sure how. The results should look like this:
RABBIT: GREY, FURRY, BOUNCES, CUTE
RABBIT: WHITE, FURRY, BOUNCES, CUTE
RABBIT: RED, FURRY, BOUNCES, CUTE
RABBIT: GREY, FURRY, SCAMPERS, CUTE
RABBIT: WHITE, FURRY, SCAMPERS, CUTE
RABBIT: RED, FURRY, SCAMPERS, CUTE
The array (and it's child arrays) will have unknown lengths, so I've used the for loop. Here is the code so far:
window.onload = function (){
var myObject = {
name: 'RABBIT',
arrayOfValues : [
['GREY','WHITE','RED'],
['FURRY'],
['BOUNCES', 'SCAMPERS'],
['CUTE']
]
};
var results = [];
for (i=0;i<myObject.arrayOfValues.length;i++){
for (j=0; j<myObject.arrayOfValues[i].length;j++){
if(myObject.arrayOfValues[i].length>1) {
var currentProperty = myObject.arrayOfValues[i][j];
myFunc();
}
else {
var currentProperty = myObject.arrayOfValues[i][0];
myFunc();
};
};
};
function myFunc(){
results = results.concat(currentProperty);
if (results.length == myObject.arrayOfValues.length){
var finalResults = myObject.name + ': ' + results
console.log(finalResults);
};
};
};
PS - The form of the data is not set in stone, I just used an object for convenience.
Thanks, Paul
You can make a recursive function call with an increasing index parameter, as well as a string to which you append the new part of the string and return.
var arrayOfArrays = [
['big', 'red'],
['red', 'yellow', 'blue'],
['dog', 'cat']
];
var strings = [];
function eachStep(string_so_far, array_index) {
if (array_index < arrayOfArrays.length) {
for (var i = 0; i < arrayOfArrays[array_index].length; i++) {
var string_for_this_step = string_so_far + arrayOfArrays[array_index][i] + " ";
var string_returned = eachStep(string_for_this_step, array_index+1);
if (string_returned !== "") {
strings.push(string_returned);
}
}
return "";
} else {
return string_so_far;
}
}
eachStep("", 0);
console.log(strings);
Recursion is the native solution here:
// Object as described by question:
var myObject = {
name: 'RABBIT',
arrayOfValues: [
['GREY', 'WHITE', 'RED'],
['FURRY'],
['BOUNCES', 'SCAMPERS'],
['CUTE']
]
};
function permutations(arrays, current_array, idx, results) {
// Init head and results in case this is the first iteration:
idx = idx || 0;
results = results || [];
current_array = current_array || [];
// If there's nothing more to add:
if (arrays.length == idx) {
results.push(current_array);
return;
}
// Otherwise, iterate current level and concat values, while calling next level:
arrays[idx].forEach(function(subArrayItem) {
permutations(arrays, current_array.concat(subArrayItem), idx + 1, results)
});
return results;
}
The function above will return a set of arrays having all combinations, next is a helper function for printing:
// Helper method to print resulting arrays:
function print(obj) {
var separator = "\n"
var prefix = obj.name + ": ";
// Joins the resulting sets with the prefix, and returns printable string:
return prefix + permutations(obj.arrayOfValues).join(separator + prefix)
}
console.log(print(myObject));

Categories