how can I access the previous element of this array of objects by the attribute "id", when the id is not sequenced one after the other. Assuming im in the las item of this array (id 6) and want to access to the previous one (id 4), but the code need to be automatic, like dont the only that element, I think it need to ask if the previous id is "null" to substract n number from the id to reach that element and to work in every part of the array. Thanks
[
{
"id": 1,
"nombre": "DITTO-X2 Looper",
"precio": "10999",
"img": "DITTO-X2.png",
"categoria": "pedales",
"sub_categoria": "loop_pedal",
"descripcion": "looper",
"marca": "ditto"
},
{
"id": 2,
"nombre": "Guitarra Taylor 562ce",
"precio": "73999",
"img": "guitarra562ce.png",
"categoria": "cuerdas",
"sub_categoria": "guitarra_acustica",
"marca": "taylor",
"descripcion": "Taylor’s Grand Concert 12-strings reaffirm Taylor’s heritage of easy-playing double course instruments thanks to a lap-friendly body size, a 12-fret neck, and a 24-7/8-inch scale length. The slinky handfeel makes fretting and bending strings easier, the neck and body are comfortably balanced, and the compact body produces a clear 12-string voice. The hardwood mahogany top adds just enough compression to the attack to smooth out the response, bringing an appealing consistency across the tonal spectrum, while still capturing the beautiful octave shimmer. V-Class bracing adds another dimension of musicality, improving volume and sustain so that notes and chords bloom and expand as they resonate. It makes a great 12-string choice for tracking in a studio, and behaves well with other instruments in a live setting. Refined aesthetic touches include a shaded edgeburst body and neck, faux tortoise shell binding, a rosette of faux tortoise shell and grained ivoroid, and a grained ivoroid Century fretboard inlay."
},
{
"id": 4,
"nombre": "BC-1x",
"precio": "38000",
"img": "1633645625329_img_.png",
"categoria": "pedales",
"sub_categoria": "bass_pedal",
"descripcion": "Pedal",
"marca": "boss"
},
{
"id": 6,
"nombre": "VE-500",
"precio": "30000",
"img": "1634188562527_img_.jpg",
"sub_categoria": "vocal_pedal",
"marca": "BOSS",
"descripcion": "If you’re like most guitarists, you spend a lot of time choosing the right amps and pedals to craft your own personalized sound. But if you sing in your band as well, it hasn’t always been so easy to give your vocal sounds that same attention to detail—until now. The advanced VE-500 Vocal Performer provides everything you need to achieve impressive vocal harmonies and effects on stage, and all in streamlined stompbox that integrates seamlessly with the regular guitar effects on your pedalboard."
}
]
Find index by Array.findIndex then get the result by Array[index-1].
const inputArray = [{
"id": 1,
"nombre": "DITTO-X2 Looper",
},
{
"id": 2,
"nombre": "Guitarra Taylor 562ce"
},
{
"id": 4,
"nombre": "BC-1x"
},
{
"id": 6,
"nombre": "VE-500"
}
]
const inputId = 6;
const indexById = inputArray.findIndex(e => e.id == inputId);
console.log(inputArray[indexById-1]);
Here is a step by step solution:
var currentId = 6;
Use findIndex to find the index of the object with currentId (https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex)
var currentIndex = arr.findIndex(function (item) {
return item.id === currentId;
});
If the index is 0 there are no previous item, if it's -1 there are no item with id: currentId
if (currentIndex === 0 || currentIndex === -1) {
// Invalid currentIndex
}
Get the array item with index currentIndex - 1
var previousElement = arr[currentIndex - 1];
Related
I'm creating a server using node and want to output JSON data, when a specific ID is clicked.
I've set up a dynamic URL which will pull the data from the clicked video using params and then compare it with the one from the JSON data, using .find()
When I log out the "req.params.id" I get the clicked ID. However, when I log out the .find() function it just gives me an undefined.
const selectedVideoData = fs.readFileSync("./data/video-details.json");
app.get("/videos/:id", (req, res) => {
const id = req.params.id;
const findClickedId = selectedVideoData.find((video) => video.id === id);
res.send(findClickedId);
});
[
{
"id": "84e96018-4022-434e-80bf-000ce4cd12b8",
"title": "BMX Rampage: 2021 Highlights",
"channel": "Red Cow",
"image": "https://i.imgur.com/l2Xfgpl.jpg",
"description": "On a gusty day in Southern Utah, a group of 25 daring mountain bikers blew the doors off what is possible on two wheels, unleashing some of the biggest moments the sport has ever seen. While mother nature only allowed for one full run before the conditions made it impossible to ride, that was all that was needed for event veteran Kyle Strait, who won the event for the second time -- eight years after his first Red Cow Rampage title",
"views": "1,001,023",
"likes": "110,985",
"duration": "4:01",
"video": "https://project-2-api.herokuapp.com/stream",
"timestamp": 1626032763000,
"comments": [
{
"id": "35bba08b-1b51-4153-ba7e-6da76b5ec1b9",
"name": "Micheal Lyons",
"comment": "They BLEW the ROOF off at their last event, once everyone started figuring out they were going. This is still simply the greatest opening of an event I have EVER witnessed.",
"likes": 0,
"timestamp": 1628522461000
},
{
"id": "091de676-61af-4ee6-90de-3a7a53af7521",
"name": "Gary Wong",
"comment": "Every time I see him shred I feel so motivated to get off my couch and hop on my board. He’s so talented! I wish I can ride like him one day so I can really enjoy myself!",
"likes": 0,
"timestamp": 1626359541000
},
{
"id": "66b7d3c7-4023-47f1-a02c-520c9ca187a6",
"name": "Theodore Duncan",
"comment": "How can someone be so good!!! You can tell he lives for this and loves to do it every day. Every time I see him I feel instantly happy! He’s definitely my favorite ever!",
"likes": 0,
"timestamp": 1626011132000
}
]
},
{
"id": "c05b9a93-8682-4ab6-aff2-92ebb4bbfc14",
"title": "Become A Travel Pro In One Easy Lesson",
"channel": "Todd Welch",
"image": "https://i.imgur.com/5qyCZrD.jpg",
"description": "Luxury is something everyone deserves from time to time. Such an indulgence can make a vacation a truly rejuvenating experience. This video will focus a lot on helping the first time or inexperienced traveler head out prepared and confident in themselves.",
"views": "2,043,765",
"likes": "400,058",
"duration": "7:26",
"video": "https://project-2-api.herokuapp.com/stream",
"timestamp": 1625158995000,
"comments": [
{
"id": "ade82e25-6c87-4403-ba35-47bdff93a51c",
"name": "Mattie Casarez",
"comment": "This is exactly the kind of advice I’ve been looking for! One minute you’re packing your bags, the next you’re dancing around in the streets without a care in the world.",
"likes": 0,
"timestamp": 1625250720000
},
{
"id": "bf704c76-cba9-462e-ac0a-166315df756c",
"name": "Taylor Jade",
"comment": "Excellent tips! Another idea is to keep all of your important belongings like your passport inside a waterproof bag. Perfect for those last minute trips to the beach, trust me.",
"likes": 0,
"timestamp": 1625238122000
},
{
"id": "ec2bec8d-ea2b-458e-9d93-b7f929a8659b",
"name": "Adnan Natt",
"comment": "Who ever knew travel could be so easy? Looking forward to getting to put this into practice when I fly away in the near future. Wish me good luck!",
"likes": 0,
"timestamp": 1625177192000
}
]
}
]
You need to parse json since fs.readFileSync return string
const rawSelectedVideoData = fs.readFileSync("./data/video-details.json");
const selectedVideoData = JSON.parse(rawSelectedVideoData)
app.get("/videos/:id", (req, res) => {
const id = req.params.id;
const findClickedId = selectedVideoData.find((video) => video.id === id);
res.send(findClickedId);
});
fs.readFileSync returns a string and an object literal, so .find shouldn't work at all.
Try instead:
const selectedVideoData = require("./data/video-details.json");
If the array you posted is the exact response you get from const selectedVideoData = fs.readFileSync("./data/video-details.json"); then make sure that id from const id = req.params.id; is a string and it should work. I have tested it on my end and it works perfectly. Though I've subbed const id = req.params.id; for const id = "84e96018-4022-434e-80bf-000ce4cd12b8"; which is the first element in your array as I don't have access to your server and it works.
Try this one:
const selectedVideoData = require("./data/video-details.json");
app.get("/videos/:id", (req, res) => {
const id = req.params.id;
const findClickedId = selectedVideoData.find((video) => video.id === id);
res.send(findClickedId);
});
So I am using Lunr.js for my search function. Everything is working nice and dandy BUT, when I search certain keywords like "God" and "church" I get unacceptably long search times. I mean like, 30 secs and even beyond 1 min long. I'm sure it must be the logic I am using that is causing this, at least I think it is. The aim of my Search Function is to search the users input and return only the sentences where the key word is found along with the name of the book and the page where the searchQuery is found. My goal is to have a search function that can work offline. This is a Cordova project. I have commented everything so that you can follow the logic easily. Thank you for your time and input!
function searchFunction() {
//Clears results-wrapper Html element
document.querySelector(".results-wrapper").innerHTML = "";
//Store query in localDB
searchQuery = document.querySelector("#search-id").value;
localStorage.setItem("searchQuery", searchQuery);
//Returns from the index only the books which contains the query
var results = idx.search(searchQuery);
//Run through "results" and return all the text where the query is found
results.forEach(function (entry) {
//documents contains the database of all the books from my json file
documents.find(findSearchQuery);
//Searches only the text of the doc/books found in results variable
function findSearchQuery(doc) {
//searchQuery is the users input
let re = new RegExp(searchQuery, "i");
//if the book's name matches reference in "results"
if (doc.name == entry.ref) {
//And if the searchQuery is found in Books text
if (doc.text.match(re)) {
//Break up the block of text into sentences
var sentences = doc.text.match(/[^\.!\?]+[\.!\?]+/g);
sentences.forEach(function (sentence) {
//Find the sentence inside the sentences array and return the one with the searchQuery
//Populate HTML element "results-wrapper" with the results
if (sentence.match(re)) {
var anchor = document.createElement("a");
anchor.className = "anchorSearchResult";
anchor.href = doc.href;
//Create "div" element
var div = document.createElement("div");
div.className = "div-test";
//Creates "h4" element for title
var h4 = document.createElement("h4");
var title = document.createTextNode(doc.name);
h4.className = "title-results";
//Creates "p" element for sentence
var textElement = document.createElement(p);
var searchResult = document.createTextNode(sentence);
textElement.className = "text-results";
//Creates "p" element for page
var p = document.createElement("p");
var pageResult = document.createTextNode(doc.page);
p.className = "page-results";
h4.appendChild(title);
textElement.appendChild(searchResult);
p.appendChild(pageResult);
div.appendChild(h4);
div.appendChild(textElement);
div.appendChild(p);
anchor.appendChild(div);
document.querySelector(".results-wrapper").appendChild(anchor);
anchor.addEventListener("click", returnSearchResultId);
function returnSearchResultId(e) {
//store selectorId value of document
localStorage.setItem("selectorId", doc.selectorId);
}
// Highlight Function
var instance = new Mark(
document.querySelector(".results-wrapper")
);
instance.mark(searchQuery, {
element: "span",
className: "highlight",
});
}
});
}
}
}
});
}
And here is just a snippet of my json file that is loaded in my "documents" variable.
[
{
"name": "Pre-Eleventh-Hour Extra",
"year": "1941",
"text": "Pre-\"Eleventh Hour\" Extra MYSTERY OF MYSTERIES EXPOSED!",
"page": "1TR 2",
"href": "tracks/tr1.html#page-2.subHeading",
"selectorId": "#page-2\\.subHeading"
},
{
"name": "Pre-Eleventh-Hour Extra",
"year": "1941",
"text": "In the interest of reaching every truth-seeking mind that desires to escape the path that leads to destruction of both body and soul, this tract will be distributed free of charge as long as this issue lasts.",
"page": "1TR 2",
"href": "tracks/tr1.html#page-2.1",
"selectorId": "#page-2\\.1"
},
{
"name": "Pre-Eleventh-Hour Extra",
"year": "1941",
"text": "PREFACE PERSONALLY WATCHING FOR EVERY RAY OF LIGHT.",
"page": "1TR 3",
"href": "tracks/tr1.html#page-3.preface",
"selectorId": "#page-3\\.preface"
},
{
"name": "Pre-Eleventh-Hour Extra",
"year": "1941",
"text": "One who entrusts to another the investigation of a message from the Lord, is making flesh his arm, and thus is foolishly acting as without a mind of his own. And ”the mind that depends upon the judgment of others is certain, sooner or later, to be misled. ” -- Education, p. 231.",
"page": "1TR 3",
"href": "tracks/tr1.html#page-3.1",
"selectorId": "#page-3\\.1"
},
{
"name": "Pre-Eleventh-Hour Extra",
"year": "1941",
"text": "Similarly, one who allows prejudice to bar him from a candid investigation of anything new, coming in the name of the Lord, is unwittingly an infidel.",
"page": "1TR 3",
"href": "tracks/tr1.html#page-3.2",
"selectorId": "#page-3\\.2"
},
{
"name": "Pre-Eleventh-Hour Extra",
"year": "1941",
"text": "Likewise he who is satisfied with his present attainments in the Word of God, says in effect: \"I am rich, and increased with goods, and have need of nothing.",
"page": "1TR 3",
"href": "tracks/tr1.html#page-3.3",
"selectorId": "#page-3\\.3"
},
{
"name": "Pre-Eleventh-Hour Extra",
"year": "1941",
"text": "All these, in variously acting out the part which provoked the condemnation written against the Laodiceans, thereby fulfilling the prophecy which they ought not fulfill, are preparing themselves to be spued out (Rev. 3:14-18). And if they continue in their self-satisfied attitude that they have all the truth, and so have need of nothing more, they will spurn every new claimant to truth and toss the message into the discard because it comes through an unexpected channel. Certainly, then, were this tract not the unfolding of prophecy, the fact is inevitable that when the unfoldment did come, they would treat it in like manner, and consequently toss away their salvation!",
"page": "1TR 3",
"href": "tracks/tr1.html#page-3.4",
"selectorId": "#page-3\\.4"
},
{
"name": "Pre-Eleventh-Hour Extra",
"year": "1941",
"text": "Throughout the ages, all who have put their trust in the so-called wise men, and foremost Christians of the day, all reputedly godly men, have by these very ones been bereft of the crown of eternal life, as were the Jewish laity in the days of Christ because of their failing to assume full responsibility for their own salvation. Presumptuously trusting in the wisdom of their so-called \"great men,\" they declined to believe in Christ's words \"O Father, Lord of heaven and earth,...Thou hast hid these things from the wise and prudent, and hast revealed them unto babes.\" Matt. 11:25 \"Where is the wise? where is the scribe?...hath not God made foolish the wisdom of this world?\" 1 Cor 1:20.",
"page": "1TR 4",
"href": "tracks/tr1.html#page-4.1",
"selectorId": "#page-4\\.1"
}
]
Figured it out! It was the highlight functionality that I am getting from the Mark.js library that was causing the huge delay. After commenting it out, everything is lightening fast again.
I'm looking for best practices.
I get this product list from my API:
[
{
"id": 6,
"name": "Pechuga de pollo",
"category": "Chicken",
"existencia": 100
},
{
"id": 7,
"name": "Pierna de pavo",
"category": "Chicken",
"existencia": 100
},
{
"id": 8,
"name": "Lonja de pescado",
"category": "Fish",
"existencia": 200
},
{
"id": 9,
"name": "Coca Cola",
"category": "Soda",
"existencia": 200
},
{
"id": 10,
"name": "Jugo de naranja",
"category": "Juice",
"existencia": 200
}
]
So I need to filter this array of products by the value "Chicken".
I've tried with the filter() method and It works well.
this.chickenProducts =productList.filter(product=>product.category=="Chicken")
Then I use the v-for directive with the chickenProducts array to fill the select input that only contains chicken products.
Do you know another way to filter data from an array to fill a select input considering a criteria in Vue JS?
I'm practicing with Vue yet.
computed filter array?
By the way, I remember Vue1 can used filterBy in v-for, but Vue2 removed it.
Your way of implementation is a bit strict. What if you would want to change your filtering condition? or have multiple condition in your code?
If I were you, I would create a method which returns an array based on condition passed into it. the I iterate over that result. This is more straightforward and modular in regards of maintenance and extensibility.
I'm working on a React project that'll allow me to search through a list of games to help me decide what to play based on what I'm in the mood for, currently I can add games to a JSON file but I'm really struggling with the searching part.
Right now, to add a new game, you'll enter the title, genre(s) and a description of the game. The genre field is a ReduxForm FieldArray object, and I think that's what's giving me the trouble. Here's my current JSON file
{
"games": [
{
"name": "Rainbow Six: Siege",
"genres": [
{
"genre": "tactical"
},
{
"genre": "shooter"
}
],
"description": "tactical team based shooter",
"id": 1
},
{
"name": "Resident Evil 2",
"genres": [
{
"genre": "horror"
},
{
"genre": "survival"
},
{
"genre": "shooter"
}
],
"description": "classic resident evil 2 remake in 2019",
"id": 2
},
{
"name": "Rocket League",
"genres": [
{
"genre": "cars"
},
{
"genre": "competition"
},
{
"genre": "one more game"
}
],
"description": "soccar!",
"id": 3
}
]
}
This is the dummy data I'm using to search:
const searchedGenres = 'horror, shooter';
const searchedList = searchedGenres.split(', ');
let foundGame = [];
Once I get the search working with this data, the plan is to allow me to just type in data on the frontend in one textbox, so "horror, shooter" would be my search term. The result from this search should only return Resident Evil 2, however I'm also receiving Rainbow Six: Siege as a result, even though it's missing one of my requested genres.
searchedList.forEach(searchedGenre => {
this.props.games.map(game => {
if (
game.genres.find(
({ genre }) =>
genre.toLowerCase() ===
searchedGenre.toLowerCase().trim()
) !== undefined
) {
foundGames.push(game);
}
});
});
I understand why I'm getting both Rainbow Six and Resident Evil as a result, because I'm not actually checking that both genres are in the games genres when I add the game to the foundGames array, but I'm completely lost on how I'd go about making sure all of the genres are in a game before I add it.
This would be a bit easier if your genres was a simple array of strings rather than objects, but still you can check pretty succinctly by leveraging some() and every() within filter() (btw filter() is a better choice than map() + push() here)
let games = [{"name": "Rainbow Six: Siege","genres": [{"genre": "tactical"},{"genre": "shooter"}],"description": "tactical team based shooter","id": 1},{"name": "Resident Evil 2","genres": [{"genre": "horror"},{"genre": "survival"},{"genre": "shooter"}],"description": "classic resident evil 2 remake in 2019","id": 2},{"name": "Rocket League","genres": [{"genre": "cars"},{"genre": "competition"},{"genre": "one more game"}],"description": "soccar!","id": 3}]
const searchedGenres = 'horror, shooter';
const searchedList = searchedGenres.split(', ');
let foundGame = games.filter(game => searchedList.every(searchItem => game.genres.some(g => g.genre == searchItem) ))
console.log(foundGame)
The filter condition basically says you want every game in searchedList to match at least one genre in the game. This will make it only return games that match every genre.
app.get('/book/:bibleBook/:bibleChapter/:bibleVerse', (req, res) => {
const book = req.params.bibleBook;
const chapter = req.params.bibleChapter;
const verse = req.params.bibleVerse;
const bibleVerse = [
{
"id": 1001001,
"Book": "Genesis",
"Chapter": 1,
"Verse": 1,
"Text": "In the beginning God created the heaven and the earth."
},
{
"id": 1001002,
"Book": "Genesis",
"Chapter": 1,
"Verse": 2,
"Text": "And the earth was without form, and void; and darkness was upon the face of the deep. And the Spirit of God moved upon the face of the waters."
},
{
"id": 1001003,
"Book": "Genesis",
"Chapter": 1,
"Verse": 3,
"Text": "And God said, Let there be light: and there was light."
},
{
"id": 1001004,
"Book": "Genesis",
"Chapter": 1,
"Verse": 4,
"Text": "And God saw the light, that it was good: and God divided the light from the darkness."
},
{
"id": 1001005,
"Book": "Genesis",
"Chapter": 1,
"Verse": 5,
"Text": "And God called the light Day, and the darkness he called Night. And the evening and the morning were the first day."
}
]
res.send('This is ' + book + ' ' + chapter + ':' + verse);
});
Good evening. I am working on a website. And I'm a trying to post json data from file below on a page. It worked for me to make a url for the verse. And on the page I get the book, chapter and verse. does anybody can explain to me how I can get the text from the bibelVerse on the right page.
If you just want to return the verse text, you need to write something that will find the correct verse in your array. So I'd do something like this...
let foundVerse = bibleVerse.find(function(verseEl) {
return verseEl.book === book && verseEl.chapter === chapter && verseEl.verse === verse;
});
You'll probably also want to validate these values you're getting from req.params to make sure you have data that is valid.
At this point, you'll either have the item that matches or a null object for foundVerse. So you can write some logic to send back the correct response (I assume the text?).
if (foundVerse) {
return res.send(foundVerse.Text);
}
return res.status(404).send("No verse found.");