Related
This question already has answers here:
Get the element with the highest occurrence in an array
(42 answers)
Closed 4 months ago.
Input :
['A', 'B', 'C', 'A', 'D', 'B', 'B', 'A', 'D']
Expected output :
'B'
The output should be the element with higher occurrence. If there are two or more elements which shares the same number of occurrence, then the element which reaches the maximum count earlier in the array should be the expected output. In the above case, 'B' and 'A' has count of 3. Since 'B' reaches the max count earlier than 'A', 'B' should be the output.
I have already found the solution for this.
My Solution
let input = ['A', 'B', 'C', 'A', 'D', 'B', 'B', 'A', 'D']
const findWinner = (arr) => {
const reduced = arr.reduce((acc, value) => ({ ...acc,
[value]: (acc[value] || 0) + 1
}), {})
let pickLargest = Object.entries(reduced)
const winner = pickLargest.reduce((acc, [key, value]) => {
if (value > acc.maxValue) {
acc.maxValue = value
acc.winner = key
} else if (value == acc.maxValue) {
if (arr.lastIndexOf(key) > arr.lastIndexOf(acc.winner)) {
acc.winner = acc.winner
} else {
acc.winner = key
}
}
return acc
}, {
maxValue: 0,
winner: ''
})
return winner.winner
}
console.log(findWinner(input));
Is there any other elegant way to achieve the same result?
You could take an object for keeping track of the counts and adjust max, if necessary.
const
findWinner = array => {
const counts = {};
let max;
for (const value of array) {
counts[value] = (counts[value] || 0) + 1;
if (counts[value] <= counts[max]) continue;
max = value;
}
return max;
};
console.log(findWinner(['A', 'B', 'C', 'A', 'D', 'B', 'B', 'A', 'D']));
This should work:
const findWinner = ary => {
const occurrences = Object.fromEntries(ary.map(e => [e, 0]));
for(let el of ary){
occurrences[el]++
}
let sorted = Object.entries(occurrences).sort((a, b) => a[1] > b[1]);
return sorted[0][0];
}
Say you have the following array:
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
How would you change this array so that all the "b" items get grouped together, until you hit another "a".
So the result of the above array would look like:
['a', 'a', 'bbb', 'a', 'bb', 'a'];
I'm trying to solve a problem with wrapping span tags around words that match a patter in a React app, but this is essentially my problem.
I've been working at it for ages but can't come up with anything I'm happy with.
Any ideas?
Cheers.
Count repeating occurences, then build the result based on that:
const result = [];
let curr = array[0], count = 1;
for(const el of array.slice(1).concat(undefined)) {
if(el !== curr || el !== "b") {
result.push(curr.repeat(count));
curr = el, count = 1;
} else count++;
}
Assuming the elements will always be single letters, you can merge the elements, then match on either bs or non-bs:
ab.join('').match(/(b+|.)/g)
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
let output = ab.join('').match(/(b+|.)/g);
console.log(output);
Using Array#reduce you could do something like this.
I'm assuming the first two characters in your solution were a typo.
const data = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
const res = data
.reduce((a,c)=>{
const lastIndex = a.length - 1;
if(a[lastIndex] && a[lastIndex].includes('b') && c === 'b') a[lastIndex] += c;
else a.push(c);
return a;
}, []);
console.log(res);
I don't know how to give an explanation for this but using reduce you can do it like this:
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
function merge(arr) {
return arr.reduce((acc,cur, index) => {
if(arr[index - 1] === 'b' && cur !== 'a') {
acc[acc.length - 1] = acc[acc.length - 1] + cur;
return acc;
}
acc.push(cur);
return acc;
},[]);
}
console.log(merge(ab))
Here's what you're after:
var ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
var index = 0;
var groupedArray = [];
var firstOccurence = true;
var groupedString = "";
var grouping = false;
for (var a = 0; a < ab.length; a++) {
if (ab[a] == "a") {
if (grouping) {
grouping = false;
firstOccurence = true;
groupedArray.push(groupedString);
}
groupedArray.push(ab[a]);
} else {
if (firstOccurence) {
groupedString = "";
firstOccurence = false;
}
groupedString += ab[a];
grouping = true;
}
}
console.log(groupedArray);
If you just want to merge b then you could use reduce like this:
If the current item and the previous item are b, then append it to the last accumulator item. Else, push it to the accumulator
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a']
const output = ab.reduce((acc, c, i, arr) => {
arr[i-1] === "b" && c === "b"
? acc[acc.length - 1] += c
: acc.push(c)
return acc;
},[])
console.log(output)
You can just map through the ab array and if the current element is a, push it to a new array but if the current element is b, check if the previous element is b or not, and if it is, merge the current element to the previous element else just push the b to the new array.
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
let arr = [];
ab.map((e,i) => {
if(i > 0) { // check if element is the first one or not
if(e == "b") {
if(ab[i - 1].indexOf('b') > -1) { // check if prev element is "b" or not
arr[arr.length-1] += e; // merge if prev element is "b"
} else {
arr.push(e);
}
} else {
arr.push(e);
}
} else {
arr.push(e);
}
});
console.log(arr);
N.B. The reduce() method approach and the regex approach shown in the other answers are cleaner and more concise as compared to the map() method approach shown above though.
you can stringify your array then split it with a match of b or more or any other character
const ab = ['a', 'a', 'b', 'b', 'b', 'a', 'b', 'b', 'a'];
const res = ab.join("").match(/(b{1,}|.)/g);
console.log(res)
I have an array [a, b, c]. I want to be able to insert a value between each elements of this array like that: [0, a, 0, b, 0, c, 0].
I guess it would be something like this, but I can't make it works.
for (let i = 0; i < array.length; i++) {
newArray = [
...array.splice(0, i),
0,
...array.splice(i, array.length),
];
}
Thank you for helping me!
For getting a new array, you could concat the part an add a zero element for each element.
var array = ['a', 'b', 'c'],
result = array.reduce((r, a) => r.concat(a, 0), [0]);
console.log(result);
Using the same array
var array = ['a', 'b', 'c'],
i = 0;
while (i <= array.length) {
array.splice(i, 0, 0);
i += 2;
}
console.log(array);
A bit shorter with iterating from the end.
var array = ['a', 'b', 'c'],
i = array.length;
do {
array.splice(i, 0, 0);
} while (i--)
console.log(array);
Another way if you want to exclude the start and end of array is :
var arr = ['a', 'b', 'c']
var newArr = [...arr].map((e, i) => i < arr.length - 1 ? [e, 0] : [e]).reduce((a, b) => a.concat(b))
console.log(newArr)
You can use map() with ES6 spread syntax and concat()
var arr = ['a', 'b', 'c']
var newArr = [0].concat(...arr.map(e => [e, 0]))
console.log(newArr)
Another ES6+ version using flatmap (if creation of a new array instead is ok):
['a', 'b', 'c', 'd']
.flatMap((e, index) => index ? [e, 0] : [0, e, 0])
Another way:
var a = ['a', 'b', 'c'],
b;
b = a.reduce((arr, b) => [...arr, b, 0], []);
console.log(b);
You could use .reduce():
function intersperse(arr, val) {
return arr.reduce((acc, next) => {
acc.push(next);
acc.push(val);
return acc;
}, [val]);
}
console.log(intersperse(['a', 'b', 'c'], 0));
Or to accomplish this by modifying the original array:
function intersperse(arr, val) {
for (let i = 0; i <= arr.length; i += 2) {
arr.splice(i, 0, val);
}
return arr;
}
console.log(intersperse(['a', 'b', 'c'], 0));
You can try with the below code. It will add 0 in middle of each two element of the array
console.log(['a', 'b', 'c'].reduce((r, a) => r.concat(a,0), [0]).slice(1, -1))
You just need to loop over the array elements and add the new element in each iteration, and if you reach the last iteration add the new element after the last item.
This is how should be your code:
var arr = ['a', 'b', 'c'];
var results = [];
arr.forEach(function(el, index) {
results.push(addition);
results.push(el);
if (index === arr.length - 1)
results.push(addition);
});
Demo:
This is a Demo snippet:
var arr = ['a', 'b', 'c'];
var results = [];
var addition = 0;
arr.forEach(function(el, index) {
results.push(addition);
results.push(el);
if(index === arr.length -1)
results.push(addition);
});
console.log(results);
If you want to insert elements only after existing ones:
console.log(["a", "b", "c"].map(i => [i, 0]).flat())
You could do
let arr = ['a', 'b', 'c'];
arr = arr.reduce((a, b) => {
a.push(0);
a.push(b);
return a;
}, []);
arr.push(0);
console.log(arr);
function insert(arr, elm) {
var newArr = [];
for(var i = 0; i < arr.length; i++) { // for each element in the array arr
newArr.push(elm); // add the new element to newArr
newArr.push(arr[i]); // add the current element from arr
}
newArr.push(elm); // finally add the new element to the end of newArr
return newArr;
}
console.log(insert(["a", "b", "c"], 0));
It could be done with strings by splitting and joining.
var arr = ['a', 'b', 'c'];
var newArray = ("0," + arr.toString().split(",").join(",0,")).split(",");
console.log(newArray);
This looks like the intersperse algorithm but does some addition to the head and tail as well. So i call it extrasperse.
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
extrasperse = (x,a) => a.reduce((p,c,i) => (p[2*i+1] = c, p), Array(2*a.length+1).fill(x));
console.log(JSON.stringify(extrasperse("X",arr)));
let arr = ['a', 'b', 'c'];
function insert(items, separator) {
const result = items.reduce(
(res, el) => [...res, el, separator], [separator]);
return result;
}
console.log(insert(arr, '0'));
all of the above methods in very long strings made my android computer run on React Native go out of memory.
I got it to work with this
let arr = ['a', 'b', 'c'];
let tmpArr = [];
for (const item in arr) {
tmpArr.push(item);
tmpArr.push(0);
}
console.log(tmpArr);
Another way is to use some functional methods like zip and flat. Check out lodash.
const array = ['a', 'b', 'c']
const zeros = Array(array.length + 1).fill(0)
const result = _.zip(zeros, array).flat().filter(x => x !== undefined)
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
Straight forward way of inserting only between:
const arr = ['a', 'b', 'c'];
arr.map((v, i) => !i || i === arr.length - 1 ? [v] : [0, v]).flat()
I think this is correct, ie, just adds the element between the elements of the array, and should be pretty efficient:
const intersperse = ([first, ...tail]: any[], element: any) => (
(first === undefined) ? [] : [first].concat(...tail.map((e) => [element, e]))
);
console.log(intersperse([], 0));
console.log(intersperse([1], 0));
console.log(intersperse([1, 2, 3], 0));
Thanks for your question and thanks to all contributors, for their answers.
This would be my approach
const arr = ["a", "b", "c"];
let toAdd = 0;
for (let i = 0; i <= arr.length; i += 2) {
arr.splice(i, 0, toAdd);
}
console.log(arr);
or
const arr = ["a", "b", "c"];
let toAdd = 0;
const newArr = [];
newArr.unshift(toAdd);
for (let i = 0; i < arr.length; i++) {
newArr.push(arr[i]);
newArr.push(toAdd);
}
console.log(newArr);
Cheers
Nav
I have an Array with duplicate values.
I want to create a Set to get the distinct values of that array and remove or create a new Array that will have the same data MINUS the elements required to create the Set.
This is not just a matter of remove the duplicates, but remove a SINGLE entry of a each distinct value in the original array
Something like that works, but I wonder if there is a more direct approach:
let originalValues = [
'a',
'a',
'a',
'b',
'b',
'c',
'c',
'd'
];
let distinct = new Set(originalValues);
/*
distinct -> { 'a', 'b', 'c', 'd' }
*/
// Perhaps originalValues.extract(distinct) ??
for (let val of distinct.values()) {
const index = originalValues.indexOf(val);
originalValues.splice(index, 1);
}
/*
originalValues -> [
'a',
'a',
'b',
'c'
];
*/
Use Array#filter in combination with the Set:
const originalValues = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd'];
const remainingValues = originalValues.filter(function(val) {
if (this.has(val)) { // if the Set has the value
this.delete(val); // remove it from the Set
return false; // filter it out
}
return true;
}, new Set(originalValues));
console.log(remainingValues);
You could use closure over a Set and check for existence.
let originalValues = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd'],
result = originalValues.filter((s => a => s.has(a) || !s.add(a))(new Set));
console.log(result);
You should not use indexOf inside a loop, because it has linear cost, and the total cost becomes quadratic. What I would do is use a map to count the occurrences of each item in your array, and then convert back to an array subtracting one occurrence.
let originalValues = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd'];
let freq = new Map(); // frequency table
for (let item of originalValues)
if (freq.has(item)) freq.set(item, freq.get(item)+1);
else freq.set(item, 1);
var arr = [];
for (let [item,count] of freq)
for (let i=1; i<count; ++i)
arr.push(item);
console.log(arr);
If all items are strings you can use a plain object instead of a map.
You can create a simple Array.prototype.reduce loop with a hash table to count the number of occurrences and populate the result only if it occurs more than once.
See demo below:
var originalValues=['a','a','a','a','b','b','b','c','c','d'];
var result = originalValues.reduce(function(hash) {
return function(p,c) {
hash[c] = (hash[c] || 0) + 1;
if(hash[c] > 1)
p.push(c);
return p;
};
}(Object.create(null)), []);
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}
Instead of using Set for this you could just use reduce() and create new array with unique values and also update original array with splice().
let oV = ["a", "a", "a", "a", "b", "b", "c", "c", "d"]
var o = {}
var distinct = oV.reduce(function(r, e) {
if (!o[e]) o[e] = 1 && r.push(e) && oV.splice(oV.indexOf(e), 1)
return r;
}, [])
console.log(distinct)
console.log(oV)
As an alternate approach, you can use following algorithm that will remove only 1st entry of a duplicate element. If not duplicate, it will not remove anything.
const originalValues = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd'];
var r = originalValues.reduce(function(p, c, i, a) {
var lIndex = a.lastIndexOf(c);
var index = a.indexOf(c)
if (lIndex === index || index !== i)
p.push(c);
return p
}, [])
console.log(r)
If duplicates are not case, then you can directly remove first iteration directly
const originalValues = ['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd'];
var r = originalValues.filter(function(el, i) {
return originalValues.indexOf(el) !== i
})
console.log(r)
Is it possible to sort and rearrange an array that looks like this:
itemsArray = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
to match the arrangement of this array:
sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]
Unfortunately, I don’t have any IDs to keep track on. I would need to priority the items-array to match the sortingArr as close as possible.
Update:
Here is the output I’m looking for:
itemsArray = [
['Bob', 'b'],
['Jason', 'c'],
['Henry', 'b'],
['Thomas', 'b']
['Anne', 'a'],
['Andrew', 'd'],
]
Any idea how this can be done?
One-Line answer.
itemsArray.sort(function(a, b){
return sortingArr.indexOf(a) - sortingArr.indexOf(b);
});
Or even shorter:
itemsArray.sort((a, b) => sortingArr.indexOf(a) - sortingArr.indexOf(b));
Something like:
items = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
sorting = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
result = []
sorting.forEach(function(key) {
var found = false;
items = items.filter(function(item) {
if(!found && item[1] == key) {
result.push(item);
found = true;
return false;
} else
return true;
})
})
result.forEach(function(item) {
document.writeln(item[0]) /// Bob Jason Henry Thomas Andrew
})
Here's a shorter code, but it destroys the sorting array:
result = items.map(function(item) {
var n = sorting.indexOf(item[1]);
sorting[n] = '';
return [n, item]
}).sort().map(function(j) { return j[1] })
If you use the native array sort function, you can pass in a custom comparator to be used when sorting the array. The comparator should return a negative number if the first value is less than the second, zero if they're equal, and a positive number if the first value is greater.
So if I understand the example you're giving correctly, you could do something like:
function sortFunc(a, b) {
var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
return sortingArr.indexOf(a[1]) - sortingArr.indexOf(b[1]);
}
itemsArray.sort(sortFunc);
Case 1: Original Question (No Libraries)
Plenty of other answers that work. :)
Case 2: Original Question (Lodash.js or Underscore.js)
var groups = _.groupBy(itemArray, 1);
var result = _.map(sortArray, function (i) { return groups[i].shift(); });
Case 3: Sort Array1 as if it were Array2
I'm guessing that most people came here looking for an equivalent to PHP's array_multisort (I did) so I thought I'd post that answer as well. There are a couple options:
1. There's an existing JS implementation of array_multisort(). Thanks to #Adnan for pointing it out in the comments. It is pretty large, though.
2. Write your own. (JSFiddle demo)
function refSort (targetData, refData) {
// Create an array of indices [0, 1, 2, ...N].
var indices = Object.keys(refData);
// Sort array of indices according to the reference data.
indices.sort(function(indexA, indexB) {
if (refData[indexA] < refData[indexB]) {
return -1;
} else if (refData[indexA] > refData[indexB]) {
return 1;
}
return 0;
});
// Map array of indices to corresponding values of the target array.
return indices.map(function(index) {
return targetData[index];
});
}
3. Lodash.js or Underscore.js (both popular, smaller libraries that focus on performance) offer helper functions that allow you to do this:
var result = _.chain(sortArray)
.pairs()
.sortBy(1)
.map(function (i) { return itemArray[i[0]]; })
.value();
...Which will (1) group the sortArray into [index, value] pairs, (2) sort them by the value (you can also provide a callback here), (3) replace each of the pairs with the item from the itemArray at the index the pair originated from.
this is probably too late but, you could also use some modified version of the code below in ES6 style. This code is for arrays like:
var arrayToBeSorted = [1,2,3,4,5];
var arrayWithReferenceOrder = [3,5,8,9];
The actual operation :
arrayToBeSorted = arrayWithReferenceOrder.filter(v => arrayToBeSorted.includes(v));
The actual operation in ES5 :
arrayToBeSorted = arrayWithReferenceOrder.filter(function(v) {
return arrayToBeSorted.includes(v);
});
Should result in arrayToBeSorted = [3,5]
Does not destroy the reference array.
function sortFunc(a, b) {
var sortingArr = ["A", "B", "C"];
return sortingArr.indexOf(a.type) - sortingArr.indexOf(b.type);
}
const itemsArray = [
{
type: "A",
},
{
type: "C",
},
{
type: "B",
},
];
console.log(itemsArray);
itemsArray.sort(sortFunc);
console.log(itemsArray);
Why not something like
//array1: array of elements to be sorted
//array2: array with the indexes
array1 = array2.map((object, i) => array1[object]);
The map function may not be available on all versions of Javascript
ES6
const arrayMap = itemsArray.reduce(
(accumulator, currentValue) => ({
...accumulator,
[currentValue[1]]: currentValue,
}),
{}
);
const result = sortingArr.map(key => arrayMap[key]);
More examples with different input arrays
I would use an intermediary object (itemsMap), thus avoiding quadratic complexity:
function createItemsMap(itemsArray) { // {"a": ["Anne"], "b": ["Bob", "Henry"], …}
var itemsMap = {};
for (var i = 0, item; (item = itemsArray[i]); ++i) {
(itemsMap[item[1]] || (itemsMap[item[1]] = [])).push(item[0]);
}
return itemsMap;
}
function sortByKeys(itemsArray, sortingArr) {
var itemsMap = createItemsMap(itemsArray), result = [];
for (var i = 0; i < sortingArr.length; ++i) {
var key = sortingArr[i];
result.push([itemsMap[key].shift(), key]);
}
return result;
}
See http://jsfiddle.net/eUskE/
var sortedArray = [];
for(var i=0; i < sortingArr.length; i++) {
var found = false;
for(var j=0; j < itemsArray.length && !found; j++) {
if(itemsArray[j][1] == sortingArr[i]) {
sortedArray.push(itemsArray[j]);
itemsArray.splice(j,1);
found = true;
}
}
}
http://jsfiddle.net/s7b2P/
Resulting order: Bob,Jason,Henry,Thomas,Anne,Andrew
In case you get here needing to do this with an array of objects, here is an adaptation of #Durgpal Singh's awesome answer:
const itemsArray = [
{ name: 'Anne', id: 'a' },
{ name: 'Bob', id: 'b' },
{ name: 'Henry', id: 'b' },
{ name: 'Andrew', id: 'd' },
{ name: 'Jason', id: 'c' },
{ name: 'Thomas', id: 'b' }
]
const sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]
Object.keys(itemsArray).sort((a, b) => {
return sortingArr.indexOf(itemsArray[a].id) - sortingArr.indexOf(itemsArray[b].id);
})
let a = ['A', 'B', 'C' ]
let b = [3, 2, 1]
let c = [1.0, 5.0, 2.0]
// these array can be sorted by sorting order of b
const zip = rows => rows[0].map((_, c) => rows.map(row => row[c]))
const sortBy = (a, b, c) => {
const zippedArray = zip([a, b, c])
const sortedZipped = zippedArray.sort((x, y) => x[1] - y[1])
return zip(sortedZipped)
}
sortBy(a, b, c)
For getting a new ordered array, you could take a Map and collect all items with the wanted key in an array and map the wanted ordered keys by taking sifted element of the wanted group.
var itemsArray = [['Anne', 'a'], ['Bob', 'b'], ['Henry', 'b'], ['Andrew', 'd'], ['Jason', 'c'], ['Thomas', 'b']],
sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ],
map = itemsArray.reduce((m, a) => m.set(a[1], (m.get(a[1]) || []).concat([a])), new Map),
result = sortingArr.map(k => (map.get(k) || []).shift());
console.log(result);
I hope that I am helping someone, but if you are trying to sort an array of objects by another array on the first array's key, for example, you want to sort this array of objects:
const foo = [
{name: 'currency-question', key: 'value'},
{name: 'phone-question', key: 'value'},
{name: 'date-question', key: 'value'},
{name: 'text-question', key: 'value'}
];
by this array:
const bar = ['text-question', 'phone-question', 'currency-question', 'date-question'];
you can do so by:
foo.sort((a, b) => bar.indexOf(a.name) - bar.indexOf(b.name));
This is what I was looking for and I did for sorting an Array of Arrays based on another Array:
It's On^3 and might not be the best practice(ES6)
function sortArray(arr, arr1){
return arr.map(item => {
let a = [];
for(let i=0; i< arr1.length; i++){
for (const el of item) {
if(el == arr1[i]){
a.push(el);
}
}
}
return a;
});
}
const arr1 = ['fname', 'city', 'name'];
const arr = [['fname', 'city', 'name'],
['fname', 'city', 'name', 'name', 'city','fname']];
console.log(sortArray(arr,arr1));
It might help someone
I had to do this for a JSON payload I receive from an API, but it wasn't in the order I wanted it.
Array to be the reference array, the one you want the second array sorted by:
var columns = [
{last_name: "last_name"},
{first_name: "first_name"},
{book_description: "book_description"},
{book_id: "book_id"},
{book_number: "book_number"},
{due_date: "due_date"},
{loaned_out: "loaned_out"}
];
I did these as objects because these will have other properties eventually.
Created array:
var referenceArray= [];
for (var key in columns) {
for (var j in columns[key]){
referenceArray.push(j);
}
}
Used this with result set from database. I don't know how efficient it is but with the few number of columns I used, it worked fine.
result.forEach((element, index, array) => {
var tr = document.createElement('tr');
for (var i = 0; i < referenceArray.length - 1; i++) {
var td = document.createElement('td');
td.innerHTML = element[referenceArray[i]];
tr.appendChild(td);
}
tableBody.appendChild(tr);
});
let sortedOrder = [ 'b', 'c', 'b', 'b' ]
let itemsArray = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
a.itemsArray(function (a, b) {
let A = a[1]
let B = b[1]
if(A != undefined)
A = A.toLowerCase()
if(B != undefined)
B = B.toLowerCase()
let indA = sortedOrder.indexOf(A)
let indB = sortedOrder.indexOf(B)
if (indA == -1 )
indA = sortedOrder.length-1
if( indB == -1)
indB = sortedOrder.length-1
if (indA < indB ) {
return -1;
} else if (indA > indB) {
return 1;
}
return 0;
})
This solution will append the objects at the end if the sorting key is not present in reference array
const result = sortingArr.map((i) => {
const pos = itemsArray.findIndex(j => j[1] === i);
const item = itemsArray[pos];
itemsArray.splice(pos, 1);
return item;
});
this should works:
var i,search, itemsArraySorted = [];
while(sortingArr.length) {
search = sortingArr.shift();
for(i = 0; i<itemsArray.length; i++) {
if(itemsArray[i][1] == search) {
itemsArraySorted.push(itemsArray[i]);
break;
}
}
}
itemsArray = itemsArraySorted;
You could try this method.
const sortListByRanking = (rankingList, listToSort) => {
let result = []
for (let id of rankingList) {
for (let item of listToSort) {
if (item && item[1] === id) {
result.push(item)
}
}
}
return result
}
with numerical sortingArr:
itemsArray.sort(function(a, b){
return sortingArr[itemsArray.indexOf(a)] - sortingArr[itemsArray.indexOf(b)];
});
This seems to work for me:
var outputArray=['10','6','8','10','4','6','2','10','4','0','2','10','0'];
var template=['0','2','4','6','8','10'];
var temp=[];
for(i=0;i<template.length;i++) {
for(x=0;x<outputArray.length;x++){
if(template[i] == outputArray[x]) temp.push(outputArray[x])
};
}
outputArray = temp;
alert(outputArray)
Use the $.inArray() method from jQuery. You then could do something like this
var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
var newSortedArray = new Array();
for(var i=sortingArr.length; i--;) {
var foundIn = $.inArray(sortingArr[i], itemsArray);
newSortedArray.push(itemsArray[foundIn]);
}
Use intersection of two arrays.
Ex:
var sortArray = ['a', 'b', 'c', 'd', 'e'];
var arrayToBeSort = ['z', 's', 'b', 'e', 'a'];
_.intersection(sortArray, arrayToBeSort)
=> ['a', 'b', 'e']
if 'z and 's' are out of range of first array, append it at the end of result
this.arrToBeSorted = this.arrToBeSorted.sort(function(a, b){
return uppthis.sorrtingByArray.findIndex(x => x.Id == a.ByPramaeterSorted) - uppthis.sorrtingByArray.findIndex(x => x.Id == b.ByPramaeterSorted);
});
You can do something like this:
function getSorted(itemsArray , sortingArr ) {
var result = [];
for(var i=0; i<arr.length; i++) {
result[i] = arr[sortArr[i]];
}
return result;
}
You can test it out here.
Note: this assumes the arrays you pass in are equivalent in size, you'd need to add some additional checks if this may not be the case.
refer link
refer