I have an array in the format:
var series = [[horse,1],[cat,2],[dog,4],[dragon,4],[cow,6]]
In order to find the top 3 elements based on the 2nd parameter I sort the array. So for this purpose I use the code below:
series.sort( function(a,b) {
if (a[1] === b[1]) {
return 0;
}
else {
return (a[1] < b[1]) ? 1 : -1;
}
});
Which works fine. Then If I want to find the top 3 I can always select [0,2]. However, if the 4th value equals the the 3th then I miss it. In this case if I ask for the top 3 the output should be [[horse,1],[cat,2],[dog,4],[dragon,4] because dragon and dog have equal value (4). So, I wonder is there some library I could use out of the box or some efficient algorithm to return the top 3 values which does not necessarily mean returning top 3 element arrays?
Just build a list:
var top = [];
top.push(series[0]);
top.push(series[1]);
for (var i = 2; i < series.length && series[i][1] == series[2][1]; ++i)
top.push(series[i]);
To generalize that (a little):
function top(series, k) {
var top = [];
for (var i = ; i < k - 1; ++i)
top.push(series[i]);
for (; i < series.length && series[k-1][1] == series[i][1]; ++i)
top.push(series[i]);
return top;
}
var series = [["horse",1],["cat",2],["dog",4],["dragon",4],["cow",6]]
num = 3;
var arr = [];
for(var i=0; i<series.length; i++)
{
var curr = series[i][1];
var next = series[i][1];
if(i<num)
{
arr.push(series[i]);
}
else if(curr==next)
{
arr.push(series[i]);
break;
}
}
console.log(arr);
So I would make a second array (length of 3) and loop through the initial array. When The first three items should be automatically added to the array. Then as we loop through the first array and find values higher than the lowest value we remove the lowest value and place the new item in the new array in its proper place.
var series = [[horse,1],[cat,2],[dog,4],[dragon,4],[cow,6]];
function top3(a){
// Create a new Array to hold the top values
var top = [a[0], a[1], a[2]]; // Initialize it with the first three items
for(var i=3;i<a.length;i++){
/* Find the minimum value and its position */
var min = top[0][1];
var min_pos = 0;
for(var e=1;e<3;e++){
if(top[e][1]<min){
min = top[e][1];
min_post = e;
}
}
/* If larger than the top arrays minimum */
if( a[i][1] > min ){
/* remove the top arrays min */
top.splice(min_pos, 1);
}
/* Add the new item into the top array */
top.push(a[i]);
}
/* Now our "top" array has the items with the top 3 values, if you want them sorted use a bubble sort here, if not just return "top" */
bubbleSortByIndex(a, 1); // Sorts by the second item in an array or arrays
return top;
};
/*
Bubble Sort Algorythm adapted from http://en.wikipedia.org/wiki/Bubble_sort
*/
function bubbleSortByIndex(a, i){
var swapped;
do {
swapped = false;
for(var e=1;e<a.length-1;e++){
if( a[e-1][i] > A[e][i]){
swapped = true;
var temp = a[e-1];
a[e-1] = a[e];
a[e] = temp
}
}
} while (swapped);
return a;
}
top3(series);
This leaves the original array in tact and finds the top three items only, and sorts those. If you wanted the entire original array sorted then just call bubbleSortByIndex(series, 1) and ignore the whole "top3()" function.
Related
Maybe I have misunderstanding on Merge sort. Can someone explain to me if I break the toBeSorted list into array of sub arrays like this:
const toBeSorted = [2,4,5,1,6,8]
const brokenDown = [[2],[4],[5],[1],[6],[8]]
then I do the usual sort and merge thing with the subarrays inside brokenDown. What is the difference or drawbacks comparing to the classic original solution?
I understand merge sort as halving the original list down till each sub array only contain one item, then sort them and merge them together. So instead of halving, I just iterate through the original array and make it an array of subarrays.
I tried both solutions, the classic one took around 3000ms to sort 200,000 while my solution took 5000ms to sort the same amount of data.
So I think I am lacking some understanding on Merge Sort.
my solution full code:
(() => {
let i = 0
const data = []
const size = 200000
while (i < size) {
data.push(Math.round(Math.random() * 1000))
i++
}
function mergeSort(arr) {
if (arr.length < 2) return arr[0]
const output = []
for (let i=0; i<arr.length; i+=2) {
output.push(sortAndStitch(arr[i], arr[i+1]))
}
return mergeSort(output)
}
function breakDown(arr) {
const output = []
for (item of data) {
output.push([item])
}
return output
}
function sortAndStitch(sub1, sub2) {
const arr1 = sub1 || [], arr2 = sub2 || [], output = []
while(arr1.length && arr2.length) {
if (arr1[0] > arr2[0]) {
output.push(arr2.shift())
} else {
output.push(arr1.shift())
}
}
return output.concat(...arr1, ...arr2)
}
const start = new Date().getTime()
mergeSort(breakDown(data))
const interval = new Date().getTime() - start + 'ms'
console.log({ size, interval })
})()
the classic solution that I am comparing to:
(() => {
let i = 0
const data = []
const size = 200000
while (i < size) {
data.push(Math.round(Math.random() * 1000))
i++
}
const mergeSort = nums => {
if (nums.length < 2) {
return nums;
}
const length = nums.length;
const middle = Math.floor(length / 2);
const left = nums.slice(0, middle);
const right = nums.slice(middle);
return merge(mergeSort(left), mergeSort(right));
};
const merge = (left, right) => {
const results = [];
while (left.length && right.length) {
if (left[0] <= right[0]) {
results.push(left.shift());
}
else {
results.push(right.shift());
}
}
return results.concat(left, right);
};
const start = new Date().getTime()
mergeSort(data)
const interval = new Date().getTime() - start + 'ms'
console.log({ size, interval })
})()
The first example pushes n = 200,000 sub-arrays of size 1 to create an array of n = 200,000 sub-arrays. Then for each "pass", it indexes two sub-arrays from the array of sub-arrays, merges them into a single sub-array, and pushes that sub-array onto yet another array of sub-arrays. So the code ends up creating 19 arrays of sub-arrays (including the original), by pushing the sub-arrays onto arrays of sub-arrays, which ends up as 400000+ pushes of sub-arrays onto arrays of sub-arrays. Those arrays of sub-arrays are also consuming a lot of space.
The second example splits the array into two sub-arrays, then recursion follows only the left sub-arrays until a sub-array of size 1 is reached, then a right sub-array of size 1 is reached, and only then does merging begin, following the call chain up and down, depth first, left first. Only 18 levels of recursion occur, and the shifts and pushes are only performed on arrays of numbers, while the first example is also performing those 400000+ pushes of sub-arrays onto arrays of sub-arrays.
An indexed based merge sort (top down or bottom up) would be much faster for either first or second example, taking about 50 ms to sort 200,000 numbers. As commented above, Wikipedia has psuedo code examples:
https://en.wikipedia.org/wiki/Merge_sort
classic original solution
The "classic original solution" is bottom up merge sort. The 1945 EDVAC that Von Newmann described a merge sort for didn't have a stack. Prior to that, Hollerith card sorters, dating back to 1887, used radix sort. The IBM type 77 collators (1937) could merge two decks of sorted cards into a single merged deck, which is what probably gave Von Newmann the idea of merge sort in 1945, followed up in 1948 with a description and analysis of bottom up merge sort.
The first practical non-punched card based sorts were tape sorts (variations of bottom up merge sort), used on the Univac 1 (early 1950's) which could have up to 10 Uniservo tape drives.
Most libraries use some variation of hybrid insertion (on small sub-arrays) + bottom up merge sort for stable sort. Run time for insertion + top down merge sort is about the same, but recursion could throw a stack overflow exception mid-sort. Example hybrid insertion + bottom up merge sort (on my system (Intel 3770K 3.5 ghz, Windows 7 Pro 64 bit, to sort 200,000 numbers, Chrome takes ~40 ms, IE 11 takes ~35 ms.
function merge(a, b, bgn, mid, end) {
var i = bgn // left: a[bgn,mid)
var j = mid // right: a[mid,end)
var k = bgn // index for b[]
while(true){
if(a[i] <= a[j]){ // if left <= right
b[k++] = a[i++] // copy left
if(i < mid) // if not end of left
continue // continue back to while
do // else copy rest of right
b[k++] = a[j++]
while(j < end)
break // and break
} else { // else left > right
b[k++] = a[j++] // copy right
if(j < end) // if not end of right
continue // continue back to while
do // else copy rest of left
b[k++] = a[i++]
while(i < mid)
break // and break
}
}
}
function insertionsort(a, ll, rr)
{
var i = ll+1
while(i < rr){
var t = a[i]
var j = i
while((j > ll) && a[j-1] > t){
a[j] = a[j-1]
j -= 1}
a[j] = t
i += 1}
}
function getpasscount(n) // return # passes
{
var i = 0
for(var s = 1; s < n; s <<= 1)
i += 1
return(i)
}
function mergesort(a)
{
var n = a.length
if(n < 2) // if size < 2 return
return
var b = new Array(n) // allocate temp array
var s = 64 // set run size
if(0 != (1&getpasscount(n))) // for even # of passes
s = 32
for(var rr = 0; rr < n; ){ // do insertion sorts
var ll = rr;
rr += s;
if(rr > n)
rr = n;
insertionsort(a, ll, rr);
}
while(s < n){ // while not done
var ee = 0 // reset end index
while(ee < n){ // merge pairs of runs
var ll = ee // ll = start of left run
var rr = ll+s // rr = start of right run
if(rr >= n){ // if only left run
do // copy it
b[ll] = a[ll]
while(++ll < n)
break // end of pass
}
ee = rr+s // ee = end of right run
if(ee > n)
ee = n
merge(a, b, ll, rr, ee) // merge a[left],a[right] to b[]
}
var t = a // swap array references
a = b
b = t
s <<= 1 // double the run size
}
}
var a = new Array(200000)
for (var i = 0; i < a.length; i++) {
a[i] = Math.round(Math.random() * 1000000000)
}
console.time('measure')
mergesort(a)
console.timeEnd('measure')
for (var i = 1; i < a.length; i++) {
if(a[i-1] > a[i]){
console.log('error')
break
}
}
I need to do something like this: Let's say I have an array:
[3, 4, 1, 2]
I need to swap 3 and 4, and 1 and 2, so my array looks like [4, 3, 2, 1]. Now, I can just do the sort(). Here I need to count how many iterations I need, to change the initial array to the final output. Example:
// I can sort one pair per iteration
let array = [3, 4, 1, 2, 5]
let counter = 0;
//swap 3 and 4
counter++;
// swap 1 and 2
counter++;
// 5 goes to first place
counter++
// now counter = 3 <-- what I need
EDIT: Here is what I tried. doesn't work always tho... it is from this question: Bubble sort algorithm JavaScript
let counter = 0;
let swapped;
do {
swapped = false;
for (var i = 0; i < array.length - 1; i++) {
if (array[i] < array[i + 1]) {
const temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
swapped = true;
counter++;
}
}
} while (swapped);
EDIT: It is not correct all the time because I can swap places from last to first, for example. Look at the example code above, it is edited now.
This is most optimal code I have tried so far, also the code is accepted as optimal
answer by hackerrank :
function minimumSwaps(arr) {
var arrLength = arr.length;
// create two new Arrays
// one record value and key separately
// second to keep visited node count (default set false to all)
var newArr = [];
var newArrVisited = [];
for (let i = 0; i < arrLength; i++) {
newArr[i]= [];
newArr[i].value = arr[i];
newArr[i].key = i;
newArrVisited[i] = false;
}
// sort new array by value
newArr.sort(function (a, b) {
return a.value - b.value;
})
var swp = 0;
for (let i = 0; i < arrLength; i++) {
// check if already visited or swapped
if (newArr[i].key == i || newArrVisited[i]) {
continue;
}
var cycle = 0;
var j = i;
while (!newArrVisited[j]) {
// mark as visited
newArrVisited[j] = true;
j = newArr[j].key; //assign next key
cycle++;
}
if (cycle > 0) {
swp += (cycle > 1) ? cycle - 1 : cycle;
}
}
return swp;
}
reference
//You are given an unordered array consisting of consecutive integers [1, 2, 3, ..., n] without any duplicates.
//still not the best
function minimumSwaps(arr) {
let count = 0;
for(let i =0; i< arr.length; i++){
if(arr[i]!=i+1){
let temp = arr[i];
arr[arr.indexOf(i+1)] =temp;
arr[i] = i+1;
count =count+1;
}
}
return count;
}
I assume there are two reasons you're wanting to measure how many iterations a sort takes. So I will supply you with some theory (if the mathematics is too dense, don't worry about it), then some practical application.
There are many sort algorithms, some of them have a predicable number of iterations based on the number of items you are sorting, some of them are luck of the draw simply based on the order of the items to be sorted and which item how you select what is called a pivot. So if optimisation is very important to you, then you'll want to select the right algorithm for the purpose of the sort algorithm. Otherwise go for a general purpose algorithm.
Here are most popular sorting algorithms for the purpose of learning, and each of them have least, worst and average running-cases. Heapsort, Radix and binary-sort are worth looking at if this is more than just an theoretical/learning exercise.
Quicksort
Worst Case: Θ(n 2)
Best case: Θ(n lg n)
Average case: Θ(n lg n)
Here is a Quicksort implementation by Charles Stover
Merge sort
Worst case: Θ(n lg n)
Best case: Θ(n lg n)
Average Case: Θ(n lg n)
(note they're all the same)
Here is a merge sort implementation by Alex Kondov
Insertion sort
Worst case: Θ(n2)
Best case: Θ(n)
Average case:Θ(n2)
(Note that its worst and average case are the same, but its best case is the best of any algorithm)
Here is an insertion sort implementation by Kyle Jensen
Selection sort
Worst case: Θ(n2)
Best case: Θ(n2)
Average case: Θ(n2)
(note they're all the same, like a merge sort).
Here is a selection sort algorithm written by #dbdavid updated by myself for ES6
You can quite easily add an iterator variable to any of these examples to count the number of swaps they make, and play around with them to see which algorithms work best in which circumstance.
If there's a very good chance the items will already be well sorted, insertion sort is your best choice. If you have absolutely no idea, of the four basic sorting algorithms quicksort is your best choice.
function minimumSwaps(arr) {
var counter = 0;
for (var i = arr.length; i > 0; i--) {
var minval = Math.min(...arr); console.log("before", arr);
var minIndex = arr.indexOf(minval);
if (minval != = arr[0]) {
var temp = arr[0];
arr[0] = arr[minIndex];
arr[minIndex] = temp; console.log("after", arr);
arr.splice(0, 1);
counter++;
}
else {
arr.splice(0, 1); console.log("in else case")
}
} return counter;
}
This is how I call my swap function:
minimumSwaps([3, 7, 6, 9, 1, 8, 4, 10, 2, 5]);
It works with Selection Sort. Logic is as follows:
Loop through the array length
Find the minimum element in the array and then swap with the First element in the array, if the 0th Index doesn't have the minimum value founded out.
Now remove the first element.
If step 2 is not present, remove the first element(which is the minimum value present already)
increase counter when we swap the values.
Return the counter value after the for Loop.
It works for all values.
However, it fails due to a timeout for values around 50,000.
The solution to this problem is not very intuitive unless you are already somewhat familiar with computer science or real math wiz, but it all comes down to the number of inversions and the resulting cycles
If you are new to computer science I recommend the following resources to supplement this solution:
GeeksforGeeks Article
Informal Proof Explanation
Graph Theory Explanation
If we define an inversion as:
arr[i]>arr[j]
where "i" is the current index and "j" is the following index --
if there are no inversions the array is already in order and requires no sorting.
For Example:
[1,2,3,4,5]
So the number of swaps is related to the number of inversions, but not directly because each inversion can lead to a series of swaps (as opposed to a singular swap EX: [3,1,2]).
So if one consider's the following array:
[4,5,2,1,3,6,10,9,7,8]
This array is composed of three cycles.
Cycle One- 4,1,3 (Two Swaps)
Cycle Two- 5,2 (One Swap)
Cycle Three- 6 (0 Swaps)
Cycle Four- 10,9,7,8 (3 Swaps)
Now here's where the CS and Math magic really kicks in: each cycle will only require one pass through to properly sort it, and this is always going to be true.
So another way to say this would be-- the minimum number of swaps to sort any cycle is the number of element in that cycle minus one, or more explicitly:
minimum swaps = (cycle length - 1)
So if we sum the minimum swaps from each cycle, that sum will equal the minimum number of swaps for the original array.
Here is my attempt to explain WHY this algorithm works:
If we consider that any sequential set of numbers is just a section of a number line, then any set starting at zero should be equal to its own index should the set be expressed as a Javascript array. This idea becomes the criteria to programmatically determined if in element is already in the correct position based on its own value.
If the current value is not equal to its own index then the program should detect a cycle start and recording its length. Once the while loop reaches the the original value in the cycle it will add the minimum number of swaps in the cycle to a counter variable.
Anyway here is my code-- it is very verbose but should work:
export const minimumSwaps = (arr) => {
//This function returns the lowest value
//from the provided array.
//If one subtracts this value the from
//any value in the array it should equal
//that value's index.
const shift = (function findLowest(arr){
let lowest=arr[0];
arr.forEach((val,i)=>{
if(val<lowest){
lowest=val;
}
})
return lowest;
})(arr);
//Declare a counter variable
//to keep track of the swaps.
let swaps = 0;
//This function returns an array equal
//in size to the original array provided.
//However, this array is composed of
//boolean values with a value of false.
const visited = (function boolArray(n){
const arr=[];
for(let i = 0; i<n;i++){
arr.push(false);
}
return arr;
})(arr.length);
//Iterate through each element of the
//of the provided array.
arr.forEach((val, i) => {
//If the current value being assessed minus
//the lowest value in the original array
//is not equal to the current loop index,
//or, if the corresponding index in
//the visited array is equal to true,
//then the value is already sorted
if (val - shift === i || visited[i]) return;
//Declare a counter variable to record
//cycle length.
let cycleLength = 0;
//Declare a variable for to use for the
//while loop below, one should start with
//the current loop index
let x = i;
//While the corresponding value in the
//corresponding index in the visited array
//is equal to false, then we
while (!visited[x]) {
//Set the value of the current
//corresponding index to true
visited[x] = true;
//Reset the x iteration variable to
//the next potential value in the cycle
x = arr[x] - shift;
//Add one to the cycle length variable
cycleLength++;
};
//Add the minimum number of swaps to
//the swaps counter variable, which
//is equal to the cycle length minus one
swaps += cycleLength - 1;
});
return swaps
}
This solution is simple and fast.
function minimumSwaps(arr) {
let minSwaps = 0;
for (let i = 0; i < arr.length; i++) {
// at this position what is the right number to be here
// for example at position 0 should be 1
// add 1 to i if array starts with 1 (1->n)
const right = i+1;
// is current position does not have the right number
if (arr[i] !== right) {
// find the index of the right number in the array
// only look from the current position up passing i to indexOf
const rightIdx = arr.indexOf(right, i);
// replace the other position with this position value
arr[rightIdx] = arr[i];
// replace this position with the right number
arr[i] = right;
// increment the swap count since a swap was done
++minSwaps;
}
}
return minSwaps;
}
Here is my solution, but it timeouts 3 test cases with very large inputs. With smaller inputs, it works and does not terminate due to timeout.
function minimumSwaps(arr) {
let swaps = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] === i + 1) continue;
arr.splice(i, 1, arr.splice(arr.indexOf(i + 1), 1, arr[i])[0]); //swap
swaps++;
}
return swaps;
}
I'm learning how to make it more performant, any help is welcome.
This is my solution to the Main Swaps 2 problem in JavaScript. It passed all the test cases. I hope someone finds it useful.
//this function calls the mainSwaps function..
function minimumSwaps(arr){
let swaps = 0;
for (var i = 0; i < arr.length; i++){
var current = arr[i];
var targetIndex = i + 1;
if (current != targetIndex){
swaps += mainSwaps(arr, i);
}
}
return swaps;
}
//this function is called by the minimumSwaps function
function mainSwaps(arr, index){
let swapCount = 0;
let currentElement = arr[index];
let targetIndex = currentElement - 1;
let targetElement = arr[currentElement - 1];
while (currentElement != targetElement){
//swap the elements
arr[index] = targetElement;
arr[currentElement - 1] = currentElement;
//increase the swapcount
swapCount++;
//store the currentElement, targetElement with their new values..
currentElement = arr[index];
targetElement = arr[currentElement - 1];
}
return swapCount;
}
var myarray = [2,3,4,1,5];
var result = console.log(minimumSwaps(myarray));
you can also do it with a map. But its O(nlogn)
const minSwaps = (arr) =>{
let arrSorted = [...arr].sort((a,b)=>a-b);
let indexMap = new Map();
// fill the indexes
for(let i=0; i<arr.length; i++){
indexMap.set(arr[i],i);
}
let count = 0;
for(let i=0; i<arrSorted.length;i++){
if(arr[i] != arrSorted[i]){
count++;
// swap the index
let newIdx = indexMap.get(arrSorted[i]);
indexMap.set(arr[i],newIdx);
indexMap.set(arrSorted[i],i);
// sawp the values
[arr[i],arr[newIdx]] =[arr[newIdx],arr[i]];
}
}
return count;
}
I'm working on some codewars problems and I came to this 'remove noise thing', I guess the point is to escape backslash \ and use replace method, which was easy. But I didn't want to use replace, instead I found myself in trouble trying to remove items with splice method.
Funny thing is, when I debug in Chrome dev tools, step by step I see items get removed, but console.log spits out certain characters($/·|ªl) problematic to remove, and at the end gets returned and join with those characters. Why is that?
function removeNoise(str) {
var base = "%$&/#·#|º\ª";
var arr = str.split('');
for(var i = 0; i < arr.length; i++) {
var item = arr[i];
var condition = base.indexOf(item);
if(condition + 1) {
//works like a charm
//arr[i] = '';
arr.splice(i,1);
//this thing wont work
//when debugging it removes the items from the array
//console log print no removing
}
}
return arr.join('');
}
removeNoise('he%$&/#·#|º\ª\llo'); //=> $/·|ªllo
You're using splice to remove entries from your array, but you're then incrementing i for the next loop. If you remove the entry at index 5 from a 10-entry array, what was the entry at index 6 is now at index 5 (of what's now a 9-entry array), so you don't want to increment your index.
The solution is to use a while loop and only update i if you don't splice:
function removeNoise(str) {
var base = "%$&/#·#|º\ª";
var arr = str.split('');
var i = 0;
while (i < arr.length) {
var item = arr[i];
var condition = base.indexOf(item);
if (condition + 1) {
// Remove this entry, reuse same value for 'i'
arr.splice(i,1);
} else {
// Don't remove this entry, move to next
++i;
}
}
return arr.join('');
}
var result = removeNoise('he%$&/#·#|º\ª\llo');
var pre = document.createElement('pre');
pre.appendChild(
document.createTextNode(result)
);
document.body.appendChild(pre);
You're removing characters from your array. This will throw your indexer variable i out of sync with the characters you want to test. Easy way to fix is to start at the end of the array working your way to the beginning.
Change your for loop to this.
for(var i = arr.length -; i <= 0; i--) {
function removeNoise(str) {
var base = "%$&/#·#|º\ª";
var arr = str.split('');
for(var i = arr.length - 1; i <= 0 ; i--) {
var item = arr[i];
if(base.indexOf(item) >= 0) {
//remove the offending character
arr.splice(i,1);
}
}
return arr.join('');
}
removeNoise('he%$&/#·#|º\ª\llo'); //=> $/·|ªllo
I am trying to insert a value into an array. I am not changing the size of the array. All I want to do is insert a value and then move all numbers after the insertion to the right using this algorighm:
Go to the last element in the array n = (length-1)
If it is not the passed index (n > index), set it's value to the value of the previous element A(n) = A(n-1)
If it is the passed index (n = index), set the value to the passed value A(n) = value and exit
Move left one element n = n-1
Repeat steps 2, 3, and 4
How do I do this? Also, I can't use any built-in array functions. Here is an example of my Javascript code:
var array = [];
for(var i=1; i<=1000; i++) {
array.push(Math.round(Math.random()*100));
}
function InsertIntoArray(array,index,number){
var numCount = 0
var move = 0 ;
for(var move = array.length - 1; move > index; move--)
{
if (move > index)
{
array[i] = array[i-1];
numCount ++;
}
else (move == index)
{
array[index] = number;
numCount++;
break;
}
}
console.log(move);
console.log(numCount);
console.log(array);
}
console.log(array);
InsertIntoArray(array, 1, 11);
You're pretty close but doing a log more than required. Hopefully the comments are sufficient:
// Just use simple test cases initially
var array = [0,1,2,3];
// The original function had some unused and pointless variables,
// they're removed
function insertIntoArray(array, index, value){
// Don't allow index to be greater than length - 1
if (index > array.length - 1) return;
// Loop until the required index is reached, shifting
// values to the next higher index
for(var move = array.length - 1; move > index; move--) {
array[move] = array[move - 1];
}
// Must now have reached required index and have shifted
// values, so just insert
array[index] = value;
}
// Original array
document.write(array + '<br>');
// Do insert
insertIntoArray(array, 2, 15);
// Modified array
document.write(array);
Note that you can have sparse arrays, the above will create new elements in such arrays so they aren't sparse any more. Also, for large arrays, it will be quite inefficient, Barmar's splice + slice answer is likely better in that regard, though it does change length along the way.
You could separate the arrays into a left and right array at the index, add the item onto the left array, and remove the last item from the right one. Then combine the two arrays:
function InsertIntoArray(array,index,number){
var leftArray = array.slice(0, index);
var rightArray = array.slice(index, array.length - 1);
leftArray.push(number);
return leftArray.concat(rightArray);
}
Fiddle Example. Note using return is to change the value of the array given other than the local array value. Simply changin array in the function will not change the global array variable.
The problem with your loop was that you were using array[i] = array[i-1], but the index variable in your loop was move, not i.
You don't need to do the if inside the loop. Just insert the new element when the loop is done. You also had a syntax error in the else -- you don't put a test after else, it's automatically the opposite of the if.
function InsertIntoArray(array, index, number) {
// Move all the elements after index up by 1
for (var move = array.length - 1; move > index; move--) {
array[move] = array[move - 1];
}
// Insert the new element
array[index] = number;
}
var array = [];
for (var i = 1; i <= 30; i++) {
array.push(i);
}
document.getElementById("before").textContent = JSON.stringify(array);
InsertIntoArray(array, 1, 11);
document.getElementById("results").textContent = JSON.stringify(array);
<b>Before:</b>
<div id="before"></div>
<b>After:</b>
<div id="results"></div>
Im looking for a way to compare 2 json records on screen. The way i want is that, i want to show these 2 records side by side and mark the matched or unmatched properties.
Is there a library that does it already, and if not, how can i do it ??
Edit
My goal is to identify the same/different properties & to show them to users with different styles, rather than comparing the objects as a whole.
Someone made a jQuery plugin for this - jQuery.PrettyTextDiff.
https://github.com/arnab/jQuery.PrettyTextDiff
$("input[type=button]").click(function () {
$("#wrapper tr").prettyTextDiff({
cleanup: $("#cleanup").is(":checked")
});
});
JSFiddle
Here is a quick JavaScript function to help you compare the to JSON strings.
First, it checks that they have same number of properties, then compares that they have the same properties (by name) and then it compares the values.
You may want to tweak the value comparison (to allow for undefined or null).
Hope it is a good starter for you.
<script type="text/javascript">
var so = {}; // stackoverflow, of course.
so.compare = function (left, right) {
// parse JSON to JavaScript objects
var leftObj = JSON.parse(left);
var rightObj = JSON.parse(right);
// add object properties to separate arrays.
var leftProps = [];
var rightProps = [];
for(var p in leftObj) { leftProps.push(p); }
for(var p in rightObj) { rightProps.push(p); }
// do they have the same number of properties
if (leftProps.length != rightProps.length) return false;
// is every right property found on the left
for (var r = 0; r < rightProps.length; r++) {
var prop = rightProps[r];
if (leftProps.indexOf(prop) < 0) {
return false;
}
}
// is every left property found on the right
for (var r = 0; r < leftProps.length; r++) {
var prop = leftProps[r];
if (rightProps.indexOf(prop) < 0) {
return false;
}
}
// do the values match?
for (var q = 0; q < leftProps.length; q++) {
var propname = leftProps[q];
var leftVal = leftObj[propname];
var rightVal = rightObj[propname];
if (leftVal != rightVal) {
return false;
}
}
return true;
}
</script>