Ramda, counting value frequency in array - javascript

I have the following simple array
['a', 'b', 'a', 'c', 'a', 'c', 'd', 'a']
How can Ramda help me in achieving the following
{a: 4, b: 1, c: 2, d: 1}
a:4 represents that value a exists 4 times in the main array
b:1 represents that value b exists 1 time in the main array
c:2 represents that value c exists 2 times in the main array
d:1 represents that value d exists 1 time in the main array

Use R.countBy with R.identity as the function that generates the keys:
const data = ['a', 'b', 'a', 'c', 'a', 'c', 'd', 'a']
const result = R.countBy(R.identity, data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

Related

Efficiently sort a disordered "subset" array based on the order of an already sorted "master" array

I have two arrays of IDs. One is an unfiltered master array that has been sorted based on values in a separate dataset object, whose keys are are the aforementioned IDs). The other array is a filtered subset of master, which is sorted in the same way as master. Like so:
const dataset = {a: {...}, b: {...}, c: {...}, d: {...}, e: {...}, f: {...}, g: {...}}
const master = ['a', 'b', 'c', 'd', 'e']
const filtered = ['a', 'c', 'd']
However, sometimes, the sort criteria changes, so I re-sort the master array. I could then re-filter this newly sorted master array in order to get my filtered array, but what I would rather do is just sort the filtered array based on the new order of the master array, as I assume this would be more efficient than running my filters again.
However, I'm not sure how to do it. For clarity, I think I want a flow something like this:
const mySort = (unsortedSubset, blueprint) => {
// do sort here
}
const dataset = {a: {...}, b: {...}, c: {...}, d: {...}, e: {...}, f:
const master = ['e', 'd', 'c', 'b', 'a']
const filtered = ['a', 'c', 'd']
const sortedFiltered = mySort(filtered, master)
console.log(sortedFiltered)
// ['d', 'c', 'a']
You could filter the master array by using the filtered array for lookup.
const
mySort = (subset, blueprint) => blueprint.filter(v => subset.includes(v));
dataset = { e: {}, d: {}, c: {}, b: {}, a: {} },
master = ['e', 'd', 'c', 'b', 'a'],
filtered = ['a', 'c', 'd'],
sortedFiltered = mySort(filtered, master);
console.log(sortedFiltered);
A version with a Set
const
mySort = (subset, blueprint) => blueprint.filter(Set.prototype.has, new Set(subset));
dataset = { e: {}, d: {}, c: {}, b: {}, a: {} },
master = ['e', 'd', 'c', 'b', 'a'],
filtered = ['a', 'c', 'd'],
sortedFiltered = mySort(filtered, master);
console.log(sortedFiltered);

Are there any combination of new ES6+ operators to add concatenated fields in array of objects?

Are there any combinations of the new ES6 operators (e.g.- spread, rest, etc..) that would allow me to add a new concatenated field for all objects in an array of objects? For example, if I have the array:
myArray = [
{a: 'A', b: 'B'},
{a: 'C', b: 'D'},
{a: 'E', b: 'F'}
];
I want to create a new array, that adds a concatenated field, ab:
myConcatArray = [
{a: 'A', b: 'B', ab: 'AB'},
{a: 'C', b: 'D', ab: 'CD'},
{a: 'E', b: 'F', ab: 'EF'}
];
Obviously this can easily be done by iterating over the elements in the array, but is there a way to do so more concisely by using the new ES6+ operators?
Use .map() to make a new array by transforming an existing array:
myArray.map(obj => ({...obj, ab: obj.a + obj.b}))

Split array keeping chosen index on center

I have an Array like that: [ 'a', 'b', 'c', 'd', 'e' ]. I need to split it in the half, but chosing an index to be the new center, i.e. always keeping the same number of elements before and after the index choosen to be the new center. Examples of the desired result:
// index: 1
[ 'e', 'a', 'b', 'c', 'd' ]
// index: 3
[ 'b', 'c', 'd', 'e', 'a' ]
I tried some things with slice and negative values:
(function splitChosingMiddle(arr, index) {
const half = Math.floor(arr.length / 2)
return [
...arr.slice(index - half),
...arr.slice(index, half + 1)
]
})([ 'a', 'b', 'c', 'd', 'e' ], 0)
But it only works if the new center is the 0 index, any other index crashs the logic. I believe I'm misunderstanding the use of negative lengths for splice.
Someone could help me with this algorithm?
try something this
function rotate (array, index) {
var head = array.slice();
var tail = head.splice(array.length - index, index);
return tail.concat(head);
}
should do the trick. But try to understand it
Find the delta between the index and the middle, slice the items using the delta to move that amount to the start/end of the array:
function splitChosingMiddle(arr, index) {
const half = Math.floor((arr.length) / 2)
const delta = index - half
return [
...arr.slice(delta, arr.length),
...arr.slice(0, delta)
]
}
console.log(JSON.stringify(splitChosingMiddle([ 'a', 'b', 'c', 'd', 'e' ], 0)));
console.log(JSON.stringify(splitChosingMiddle([ 'a', 'b', 'c', 'd', 'e' ], 1)));
console.log(JSON.stringify(splitChosingMiddle([ 'a', 'b', 'c', 'd', 'e' ], 2)));
console.log(JSON.stringify(splitChosingMiddle([ 'a', 'b', 'c', 'd', 'e' ], 3)));
console.log(JSON.stringify(splitChosingMiddle([ 'a', 'b', 'c', 'd', 'e' ], 4)));
This looks like a CS homework problem, so I'll give a hint rather than a direct solution to save you some fun.
It looks like index is a number of rotations - i.e. take the last item from the list and put at the beginning (javascript has shift and pop that may be helpful).

Can't find lodash.pull function for Ruby array

Is there any utility function which works like lodash.pull but for Ruby arrays?
You can use the delete method to remove occurrences of a single value:
arr = ['a', 'b', 'c', 'b', 'c', 'd']
arr.delete 'b'
# ['a', 'c', 'c', 'd']
Or you can use the - or -= operator to delete an array of values.
arr = ['a', 'b', 'c', 'b', 'c', 'd']
arr -= ['a', 'c']
# ['b', 'b', 'd']
There are several equivalent of the _.pull, but they work with one value at a time.
You could use
[:a, :b, :c, :a, :b].delete(:a) # => can't accept multiple arguments
Or you could use
[:a, :b, :c, :a, :b].delete_if{|x| [:a, :b].include? x}
Or you could use #andrunix approach above by subtracting the array:
arr = ['a', 'b', 'c', 'b', 'c', 'd']
arr -= ['a', 'c']

Stuck on creating a function that will return objects

Hi I was wondering if I can get some help here I am stuck. I am trying to create a histogram function that takes an array like ['a', 'a', 'b', 'c', 'b', 'a'] and returns {a:3, b:2, c:1} using the reduce function to build the histogram function. But I am stuck on what the callback function should be.
Thank you for any responses.
You can reduce your array like this:
['a', 'a', 'b', 'c', 'b', 'a'].reduce(function(obj, value) {
obj[value] = obj[value] || 0;
obj[value]++;
return obj;
}, {});
If your environment supports Object.assign() and ES6 you can also do this:
['a', 'a', 'b', 'c', 'b', 'a']
.reduce((a, b) => Object.assign(a, {[b]: a[b] ? ++a[b] : 1}), {});
Try to iterate over the array and fill/increment the object's value accordingly,
var x = ['a', 'a', 'b', 'c', 'b', 'a'];
var y = {};
x.forEach(function(itm){
y[itm] = ++y[itm] || 1;
});

Categories

Resources