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']
Related
I have two arrays that represent a fifo-like state, an old state and a new state. I need a function that finds the newly added items by comparing the new array with the old one. Below 3 examples of two arrays where 1 has items added to the front of it compared to the other:
// Input 1
const arr1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
const arr2 = ['a', 'b', 'a', 'b', 'c', 'd', 'e', 'f', 'g']; // added 'a' and 'b' in front
// Input 2
const arr3 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
const arr4 = ['q', 'r', 'a', 'b', 'c', 'd', 'e', 'f', 'g']; // added 'q' and 'r' in front
// Input 3
const arr5 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
const arr6 = ['a', 'b', 'q', 'a', 'b', 'c', 'd', 'e', 'f']; // added 'a' 'b' and 'q' in front
// New Input 4
const arr7 = ['a', 'b', 'a', 'b', 'c', 'd', 'e', 'f', 'g'];
const arr8 = ['a', 'b', 'a', 'b', 'a', 'b', 'c', 'd', 'e']; // added 'a' and 'b' in front
Note that the amount of newly added items is removed from the back of the array.
Here the desired functionality getItemsAdded(arr1, arr2) function:
// Desired output for 'getItemsAdded()' function
console.log(getItemsAdded(arr1, arr2)); // [ 'a', 'b' ]
console.log(getItemsAdded(arr3, arr4)); // [ 'q', 'r' ]
console.log(getItemsAdded(arr5, arr6)); // [ 'a', 'b', 'q' ]
// New
console.log(getItemsAdded(arr7, arr8)); // [ 'a', 'b' ]
It feels like such a simple problem, but I cant get my head around it.. I couldn't solve it with solutions provided here How to get the difference between two arrays in JavaScript?, since its a different problem.
Code can tell more words, Then my silly explanation...
// Input 1
const arr1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
const arr2 = ['a', 'b', 'a', 'b', 'c', 'd', 'e', 'f', 'g']; // added 'a' and 'b' in front
// Input 2
const arr3 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
const arr4 = ['q', 'r', 'a', 'b', 'c', 'd', 'e', 'f', 'g']; // added 'q' and 'r' in front
// Input 3
const arr5 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'];
const arr6 = ['a', 'b', 'q', 'a', 'b', 'c', 'd', 'e', 'f']; // added 'a' 'b' and 'q' in front
const arr7 = ['a', 'b', 'a', 'b', 'c', 'd', 'e', 'f', 'g'];
const arr8 = ['a', 'b', 'a', 'b', 'a', 'b', 'c', 'd', 'e']; // added 'a' and 'b' in front
// Desired output for 'diff()' function
console.log([...getItemsAdded(arr1, arr2)]); // [ 'a', 'b' ]
console.log([...getItemsAdded(arr3, arr4)]); // [ 'q', 'r' ]
console.log([...getItemsAdded(arr5, arr6)]); // [ 'a', 'b', 'q' ]
console.log([...getItemsAdded(arr7, arr8)]); // [ 'a', 'b' ]
function startsWith(arr1, arr2) {
for (let i = 0; i < arr1.length; i++)
if (arr1[i] != arr2[i])
return false
return true
}
function* getItemsAdded(arr1, arr2) {
while (!startsWith(arr2, arr1)) yield arr2.shift()
}
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>
This question already has answers here:
Merge/flatten an array of arrays
(84 answers)
Closed 3 years ago.
I want to populate an autocomplete search box.
I am using this, but is there a better way?
var array1 = [
['a', 'b', 'c'],
['d', 'e', 'f'],
['g', 'h', 'i']
];
console.log(array1[0].concat(array1[1], array1[2]));
One option is using flat()
var array1 = [
['a', 'b', 'c'],
['d', 'e', 'f'],
['g', 'h', 'i']
];
console.log( array1.flat() );
Or concat and spread syntax
var array1 = [
['a', 'b', 'c'],
['d', 'e', 'f'],
['g', 'h', 'i']
];
console.log( [].concat(...array1) )
I have this array of persons
personsList = [
{cities: ['A', 'B', 'C']},
{cities: ['A', 'B', 'C']},
{cities: ['A', 'B', 'C']},
{cities: ['A', 'B', 'C', 'D']}
]
in every object inside there more details beside cities but I want to make an array with all the cities inside - unique. so the result will be
['A', 'B', 'C', 'D']
I tried doing something like
const allCities = personsList.map(p => p.cities)
but then I got an array of arrays, what is the best approach for this one ? thanks.
You can try following using Set
var personsList = [
{cities: ['A', 'B', 'C']},
{cities: ['A', 'B', 'C']},
{cities: ['A', 'B', 'C']},
{cities: ['A', 'B', 'C', 'D']}
]
// cities will have all the cities with duplicates
const allCities = personsList.reduce((a,c) => [...a, ...c.cities], []);
// create set from array - removes duplicate and then create array back from set
console.log(Array.from(new Set(allCities)));
You can array#map all cities and then concat them into one array. Then using Set you can get the unique city.
const personsList = [ {cities: ['A', 'B', 'C']}, {cities: ['A', 'B', 'C']}, {cities: ['A', 'B', 'C']}, {cities: ['A', 'B', 'C', 'D']} ],
uniqueCity = Array.from(new Set([].concat(...personsList.map(({cities}) => cities))));
console.log(uniqueCity);
You could use directly a Set for getting unique values.
var personsList = [{ cities: ['A', 'B', 'C'] }, { cities: ['A', 'B', 'C'] }, { cities: ['A', 'B', 'C'] }, { cities: ['A', 'B', 'C', 'D'] }],
unique = Array.from(
personsList.reduce(
(s, { cities }) => cities.reduce((t, c) => t.add(c), s),
new Set
)
);
console.log(unique);
I think this is the effect that you are looking for, by using set you guarantee yourself that there are only unique elements.
let personsList = [
{cities: ['A', 'B', 'C']},
{cities: ['A', 'B', 'C']},
{cities: ['A', 'B', 'C']},
{cities: ['A', 'B', 'C', 'D']}
]
const allCities = personsList.reduce((acc,e) => {
e.cities.map(x=>{
acc.add(x)
})
return acc
}, new Set())
console.log(Array.from(allCities))
const personsList = [
{ cities: ['A', 'B', 'C'] },
{ cities: ['A', 'B', 'C'] },
{ cities: ['A', 'B', 'C'] },
{ cities: ['A', 'B', 'C', 'D'] }
];
const allCities = [...new Set([].concat(...personsList.map(({ cities }) => cities)))];
console.log(allCities);
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;
});