I have this array :
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
and I want to remove array value sequentially from first index.
so it will produce:
[ "apple", "orange", "watermelon", "blueberry", "lemon", "guava" ]
[ "orange", "watermelon", "blueberry", "lemon", "guava" ]
[ "watermelon", "blueberry", "lemon", "guava" ]
[ "blueberry", "lemon", "guava" ]
[ "lemon", "guava" ]
[ "guava" ]
I've already tried this code:
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
runLoop = async () => {
for(const item of items){
await new Promise( resolve => setTimeout( resolve, 1000 ));
console.log(items);
remove(items, item);
console.log('------------');
}
}
function remove(array, element) {
console.log('deleting '+element);
const index = array.indexOf(element);
array.splice(index, 1);
}
but the result it's not what I expected,
here is the result:
Array(6) [ "apple", "orange", "watermelon", "blueberry", "lemon", "guava" ]
Array(5) [ "orange", "watermelon", "blueberry", "lemon", "guava" ]
Array(4) [ "orange", "blueberry", "lemon", "guava" ]
The problem is that array iterable is live - if you invoke the iterator with for..of and mutate the array while that iterator is still being used, the resulting items iterated over will likely be unintuitive - some indicies may be missed. It's kind of like what's going on here:
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
for (let i = 0; i < items.length; i++) {
console.log('item: ', items[i]);
items.splice(i, 1);
}
The loop only runs 3 times, because you're removing items from the array while you're iterating over it, so some indicies get skipped.
One possibility is to make a copy of the array first, when invoking the iterator with for..of, so that the iterator will always iterate over every item that was in the original array sequentially:
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
runLoop = async () => {
for(const item of items.slice()){
await new Promise( resolve => setTimeout( resolve, 300 ));
console.log(items);
remove(items, item);
console.log('------------');
}
}
function remove(array, element) {
console.log('deleting '+element);
const index = array.indexOf(element);
array.splice(index, 1);
}
runLoop();
You need to splice at index zero,
array.splice(0, 1);
or just shift the first element.
array.shift();
An alternative can a recursive function and shift which removes the first element from an array
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
function removeElem(arr) {
if (arr.length !== 1) {
console.log(arr)
arr.shift();
removeElem(arr)
} else {
console.log(arr)
}
}
removeElem(items)
You can use Array.slice to achieve this. When using splice, remember that it will affect the original array, which should not be done according to the functional approach of javascript. Functional programming doesn't recommend to mutate the original object.
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
for(let i=0;i<items.length;i++){
console.log(items.slice(i,items.length));
}
Related
The question itself is probably in need of editing but hear me out pls. I have this:
[
["a","b","c"],
["apple", "orange", "banana"],
["kiwi", "tomato", "avocado"],
["beans", "asparagus", "spinach"]
]
I need it so that it will look like the one below:
[
{"a":"apple", "b":"orange", "c":"banana"},
{"a":"kiwi", "b":"tomato", "c":"avocado"},
{"a":"a", "b":"asparagus", "c":"spinach"}
]
I have done something like this:
const rows = [
["a","b","c"],
["apple", "orange", "banana"],
["kiwi", "tomato", "avocado"],
["beans", "asparagus", "spinach"]
]
const dataObj = {};
const dataArr = [];
if (rows.length) {
keys = rows[0];
values = rows[0];
rows.forEach((element, i) => {
values = rows[i];
keys.forEach((key, j) => {
dataObj[key] = values[j];
dataArr.push(dataObj);
});
});
}
To no avail and got something like this:
[
{"a":"apple", "b":"orange", "c":"banana"},
{"a":"apple", "b":"orange", "c":"banana"},
{"a":"apple", "b":"orange", "c":"banana"}
]
This is not the desired output. If you can help me out - and our community! - it would be super. Thanks!
You can use couple of Array functions to achieve this:
Array.shift: To pick the first element and remove it from array
Array.map: To transform items into object
const rows = [
["a", "b", "c"],
["apple", "orange", "banana"],
["kiwi", "tomato", "avocado"],
["beans", "asparagus", "spinach"]
]
const keys = rows.shift();
const map = rows.map((item) => {
const obj = {}
keys.forEach((key, index) => {
obj[key] = item[index]
})
return obj
})
console.log(map)
If you can use lodash:
Check it out in this sandbox
import _ from 'lodash';
const input = [
["a","b","c"],
["apple", "orange", "banana"],
["kiwi", "tomato", "avocado"],
["beans", "asparagus", "spinach"]
]
const keys = input[0];
const values = input.splice(1);
console.log(keys);
console.log(values);
const output = values.map(row => _.zipObject(keys, row));
console.log(output);
/*
[
{"a":"apple","b":"orange","c":"banana"},
{"a":"kiwi","b":"tomato","c":"avocado"},
{"a":"beans","b":"asparagus","c":"spinach"}
]
*/
Modified your code a little bit for the solution
const rows = [
["a","b","c"],
["apple", "orange", "banana"],
["kiwi", "tomato", "avocado"],
["beans", "asparagus", "spinach"]
]
let dataObj = {};
const dataArr = [];
if (rows.length) {
keys = rows[0];
rows.forEach((row, i) => {
if(i==0)
return
dataObj = {}
keys.forEach((key, j) => {
dataObj[key] = row[j];
});
dataArr.push(dataObj);
});
}
console.log(dataArr)
I have this array of strings:
[ "apple", "apple", "apple", "apple", "apple", "apple", ]
Is it possible to make an assertion with Chai that all elements in the array are equal to the certain value?
arrayFromApiResponse = [ "apple", "apple", "apple", "apple", "apple", "apple", ]
expectedFruit = "apple"
expect(arrayFromApiResponse).to ???
I need to test that each value in the arrayFromApiResponse is "apple"
I found this https://github.com/chaijs/Chai-Things
Seems like with this library it can be accomplished like this:
expect(arrayFromApiResponse).should.all.be.a(expectedFruit)
But is it possible to achieve this without additional library? Maybe I can make some changes to arrayFromApiResponse so it can be validated by Chai?
UPD:
I have updated the question title to prevent marking my question as duplicate with reference to this type of questions:
Check if all values of array are equal
You could use the every() method.
const arrayFromApiResponse = [ "apple", "apple", "apple", "apple", "apple", "apple", ]
const expectedFruit = "apple"
const allAreExpectedFruit = arrayFromApiResponse.every(x => x === expectedFruit);
console.log(allAreExpectedFruit);
const arrayFromApiResponse = [ "apple", "apple", "apple", "apple", "apple", "apple"]
const expectedFruit = "apple"
You can do this with filter() but the most efficient would be a good old for loop:
function test(arr, val){
for(let i=0; i<arrayFromApiResponse.length; i++){
if(arr[i] !== val) {
return false;
}
}
return true;
}
The reason this is more efficient is that this function will terminate as soon as it sees a value which doesn't equal the expected value. Other functions will traverse the entire array, which can be extremely inefficient. Use it like this:
expect(test(arrayFromApiResponse, expectedFruit)).toBe(true);
I want to count value's number.
Here is json.
x = {"first" : ["apple", "banana", "car", "day"],
"second" : ["apple","car"],
"third" : ["day"],
"fourth" " [],
"fifth" : ["apple"]
}
And I need these output.
object..???['apple']
>>>3
object..???['banana']
>>>1
object..???['car']
>>>2
object..???['day']
>>>2
object..???['elephant']
>>>0
What kind of code should I use?
I tried the following but it isn't working:
Object.values(x['day']).length;
You can get all the values in your object and put them into an array using Object.values() and .flat(). Then, you can .filter() out any items in your values array which are not your desired item. Finally, you can get the .length of this array to find how many items matched your search.
See example below:
const x = {
"first": ["apple", "banana", "car", "day"],
"second": ["apple", "car"],
"third": ["day"],
"fourth": [],
"fifth": ["apple"]
}
const countItem = (obj, search) =>
Object.values(obj).flat().filter(item => item === search).length;
console.log(countItem(x, "apple")); // 3
console.log(countItem(x, "banana")); // 1
console.log(countItem(x, "car")); // 2
console.log(countItem(x, "day")); // 2
console.log(countItem(x, "elephant")); // 0
Use flat() to flatten out the object's values and then use a reduce operation to calculate the number of times the key appears in the object:
const x = {
"first": ["apple", "banana", "car", "day"],
"second": ["apple", "car"],
"third": ["day"],
"fourth": [],
"fifth": ["apple"]
};
const count = (k) => Object.values(x).flat().reduce((a, v) => a + (k === v ? 1 : 0), 0);
console.log(count('day')); // 2
I want to add an object and delete two objects in a function
const old1 = [
{item: "apple", number: 13}
]
const old2 = [
{item: "apple", number: 13},
{item: "banana", number: 11},
{item: "orange", number: 13}
]
First, I want to add an object in the array
const add = {item: "pear", number: 3}
Then I want to check if the array has these elements, if yes, then remove them. Here I want to remove anything "banana" and "orange"
const new2 =[
{item: "pear", number: 3},
{item: "apple", number: 13}
]
I tried old1.unshift to add an element.
I also tried old2.splice(0,2) to remove elements but it is based of the index order. I should check the item property and remove the relative one.
You can use Array.push to add the element:
old1.push({item: "pear", number: 3});
And for removing based on a condition - you could put the values you want to remove in an array, then run an Array.filter
let itemsToRemove = ["banana", "orange"]
let filteredItems = old2.filter(o => !itemsToRemove.includes(o.item));
For an array of objects I use code similar to this to add/update them.
addUpdateItem(item, arr) {
let ind = arr.map(i => i.id).indexOf(item.id) //find the position of element if exists
if(ind != -1) { //this means the item was found in the array
//normally I would want to update the item if it existed
Object.assign(arr[ind], item) //update the item
//but if you wanted to remove the item instead
arr.splice(ind, 1) //removes the item
} else {
arr.push(item)
}
}
I have an array of strings which are tags of blog posts from database.
This is the example end result of a query :
["apple","banana", "apple", "orange","grapes","mango","banana"];
I need to know how many times a string is repeated in that array so I can build a sort of tag cloud.
Final end result should look like: [{name:"apple",count:2}, {name:"banana", count:2}, {name: "orange",count:1} ...];
I am using lodash in my project and would like to use it if possible. plain javascript is also fine.
You can use groupBy to do the heavy lifting then use map to format the result to your liking:
const data = ["apple", "banana", "apple", "orange", "grapes", "mango", "banana"];
const result = _.values(_.groupBy(data)).map(d => ({name: d[0], count: d.length}));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Use reduce and map
var input = ["apple","banana", "apple", "orange","grapes","mango","banana"];
var map = input.reduce( (a,c) => ( a[c] = a[c] || 0, a[c]++, a ) ,{});
var output = Object.keys( map ).map( s => ({name: s, count:map[s]}) );
Demo
var input = ["apple", "banana", "apple", "orange", "grapes", "mango", "banana"];
var map = input.reduce((a, c) => (a[c] = a[c] || 0, a[c]++, a), {});
var output = Object.keys(map).map(s => ({
name: s,
count: map[s]
}));
console.log(output);
Create a map, mapping name to count. Loop over the list, for each item, if its' in the map, increment it's count, else set its count to one.
if (tag in map) { map[tag] += 1 }
else { map[tag] = 1 }
Then you can iterate of the map and convert it to a list of objects.
To count use _.countBy(), then transform to requested form, by using _.entries(), and mapping the tuples to objects:
const data = ["apple", "banana", "apple", "orange", "grapes", "mango", "banana"];
const result = _.entries(_.countBy(data)).map(([name, count]) => ({ name, count }));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>