2.8 מחרוזות פתרון
פתרון - מחרוזות
תרגיל 1 - עיבוד מחרוזות בסיסי
// 1. capitalize
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
}
console.log(capitalize("hello WORLD")); // "Hello world"
// 2. countChar
function countChar(str, char) {
return str.split(char).length - 1;
}
console.log(countChar("hello world", "l")); // 3
// alternative with filter:
function countChar2(str, char) {
return [...str].filter((c) => c === char).length;
}
// 3. reverseString
function reverseString(str) {
return str.split("").reverse().join("");
}
console.log(reverseString("hello")); // "olleh"
// alternative with spread:
function reverseString2(str) {
return [...str].reverse().join("");
}
// 4. isPalindrome
function isPalindrome(str) {
const cleaned = str.toLowerCase().replaceAll(" ", "");
return cleaned === reverseString(cleaned);
}
console.log(isPalindrome("Race Car")); // true
console.log(isPalindrome("hello")); // false
// 5. removeVowels
function removeVowels(str) {
return str.split("").filter((c) => !"aeiouAEIOU".includes(c)).join("");
}
console.log(removeVowels("Hello World")); // "Hll Wrld"
// alternative with replaceAll:
function removeVowels2(str) {
return str.replace(/[aeiou]/gi, "");
}
תרגיל 2 - Template Literals
// 1. email template
function createEmailTemplate(name, product, price) {
const formattedPrice = price.toLocaleString("en-US", {
style: "currency",
currency: "USD"
});
return `Dear ${name},
Thank you for purchasing ${product}.
Your total is: ${formattedPrice}
Best regards,
The Store`;
}
console.log(createEmailTemplate("Alice", "Laptop", 5000));
// 2. HTML card
function createHTMLCard(title, description, imageUrl) {
return `<div class="card">
<img src="${imageUrl}" alt="${title}">
<h2>${title}</h2>
<p>${description}</p>
</div>`;
}
console.log(createHTMLCard("JavaScript", "The best language", "js.png"));
תרגיל 3 - ניתוח ועיצוב
// 1. formatPhoneNumber
function formatPhoneNumber(phone) {
// remove all non-digit characters
const digits = phone.replace(/\D/g, "");
// format as XXX-XXX-XXXX
return `${digits.slice(0, 3)}-${digits.slice(3, 6)}-${digits.slice(6)}`;
}
console.log(formatPhoneNumber("0501234567")); // "050-123-4567"
console.log(formatPhoneNumber("050-1234567")); // "050-123-4567"
console.log(formatPhoneNumber("050 123 4567")); // "050-123-4567"
// 2. extractDomain
function extractDomain(email) {
return email.slice(email.indexOf("@") + 1);
}
console.log(extractDomain("alice@gmail.com")); // "gmail.com"
console.log(extractDomain("bob@company.co.il")); // "company.co.il"
// alternative:
function extractDomain2(email) {
return email.split("@")[1];
}
// 3. maskCreditCard
function maskCreditCard(number) {
const digits = number.replace(/\D/g, "");
const lastFour = digits.slice(-4);
return `****-****-****-${lastFour}`;
}
console.log(maskCreditCard("4580123456789012")); // "****-****-****-9012"
תרגיל 4 - מניפולציות מתקדמות
// 1. toCamelCase
function toCamelCase(str) {
return str
.split(/[-_\s]+/) // split by hyphens, underscores, or spaces
.map((word, index) => {
if (index === 0) return word.toLowerCase();
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
})
.join("");
}
console.log(toCamelCase("hello world")); // "helloWorld"
console.log(toCamelCase("background-color")); // "backgroundColor"
console.log(toCamelCase("font_size")); // "fontSize"
// 2. toSnakeCase
function toSnakeCase(str) {
return str
// add underscore before uppercase letters
.replace(/([A-Z])/g, "_$1")
// replace spaces and hyphens with underscores
.replace(/[-\s]+/g, "_")
.toLowerCase()
// remove leading underscore if exists
.replace(/^_/, "");
}
console.log(toSnakeCase("Hello World")); // "hello_world"
console.log(toSnakeCase("backgroundColor")); // "background_color"
console.log(toSnakeCase("fontSize")); // "font_size"
// 3. toTitleCase
function toTitleCase(str) {
return str
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(" ");
}
console.log(toTitleCase("hello world from javascript"));
// "Hello World From Javascript"
תרגיל 5 - CSV Parser
function parseCSV(csvString) {
const lines = csvString.trim().split("\n");
const headers = lines[0].split(",");
return lines.slice(1).map((line) => {
const values = line.split(",");
const obj = {};
headers.forEach((header, index) => {
obj[header] = values[index];
});
return obj;
});
}
const csv = `name,age,city
Alice,25,Tel Aviv
Bob,30,Jerusalem
Charlie,35,Haifa`;
console.log(parseCSV(csv));
// [
// { name: "Alice", age: "25", city: "Tel Aviv" },
// { name: "Bob", age: "30", city: "Jerusalem" },
// { name: "Charlie", age: "35", city: "Haifa" }
// ]
// alternative using Object.fromEntries:
function parseCSV2(csvString) {
const lines = csvString.trim().split("\n");
const headers = lines[0].split(",");
return lines.slice(1).map((line) => {
const values = line.split(",");
return Object.fromEntries(headers.map((h, i) => [h, values[i]]));
});
}
// bonus: toCSV
function toCSV(arrayOfObjects) {
if (arrayOfObjects.length === 0) return "";
const headers = Object.keys(arrayOfObjects[0]);
const headerLine = headers.join(",");
const dataLines = arrayOfObjects.map((obj) =>
headers.map((h) => obj[h]).join(",")
);
return [headerLine, ...dataLines].join("\n");
}
const data = [
{ name: "Alice", age: "25", city: "Tel Aviv" },
{ name: "Bob", age: "30", city: "Jerusalem" }
];
console.log(toCSV(data));
// "name,age,city
// Alice,25,Tel Aviv
// Bob,30,Jerusalem"
תרגיל 6 - מנוע חיפוש פשוט
function search(text, query) {
const lowerText = text.toLowerCase();
const lowerQuery = query.toLowerCase();
// find all positions
const positions = [];
let pos = lowerText.indexOf(lowerQuery);
while (pos !== -1) {
positions.push(pos);
pos = lowerText.indexOf(lowerQuery, pos + 1);
}
// split text into sentences
const sentences = text.split(/[.!?]+/).map((s) => s.trim()).filter((s) => s);
// find the sentence for each position
const contexts = positions.map((pos) => {
return sentences.find((sentence) => {
const sentenceStart = text.indexOf(sentence);
const sentenceEnd = sentenceStart + sentence.length;
return pos >= sentenceStart && pos < sentenceEnd;
}) || "";
});
return {
count: positions.length,
positions,
contexts
};
}
const text = "JavaScript is great. I love JavaScript. JavaScript is everywhere.";
console.log(search(text, "JavaScript"));
// {
// count: 3,
// positions: [0, 27, 40],
// contexts: [
// "JavaScript is great",
// "I love JavaScript",
// "JavaScript is everywhere"
// ]
// }
תרגיל 7 - מחולל סיסמאות
function generatePassword(length, options) {
let chars = "";
if (options.uppercase) chars += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (options.lowercase) chars += "abcdefghijklmnopqrstuvwxyz";
if (options.numbers) chars += "0123456789";
if (options.symbols) chars += "!@#$%^&*()_+-=[]{}|;:,.<>?";
if (chars.length === 0) return "";
let password = "";
for (let i = 0; i < length; i++) {
const randomIndex = Math.floor(Math.random() * chars.length);
password += chars[randomIndex];
}
return password;
}
console.log(generatePassword(12, {
uppercase: true, lowercase: true, numbers: true, symbols: true
}));
// random 12-char password
console.log(generatePassword(8, {
uppercase: true, lowercase: true, numbers: true, symbols: false
}));
// random 8-char password without symbols
console.log(generatePassword(4, {
uppercase: false, lowercase: false, numbers: true, symbols: false
}));
// random 4-digit number
// bonus: password strength checker
function checkPasswordStrength(password) {
const hasLower = /[a-z]/.test(password);
const hasUpper = /[A-Z]/.test(password);
const hasNumber = /[0-9]/.test(password);
const hasSymbol = /[^a-zA-Z0-9]/.test(password);
if (password.length < 6) return "weak";
if (password.length >= 12 && hasLower && hasUpper && hasNumber && hasSymbol) {
return "strong";
}
if (password.length >= 8 && hasLower && hasUpper && hasNumber) {
return "medium";
}
return "weak";
}
console.log(checkPasswordStrength("abc")); // "weak"
console.log(checkPasswordStrength("Abc12345")); // "medium"
console.log(checkPasswordStrength("Abc123!@#xyz")); // "strong"
תרגיל 8 - עיבוד URL
// 1. parseURL
function parseURL(url) {
// extract protocol
const protocolEnd = url.indexOf("://");
const protocol = url.slice(0, protocolEnd);
let rest = url.slice(protocolEnd + 3);
// extract hash
let hash = "";
const hashIndex = rest.indexOf("#");
if (hashIndex !== -1) {
hash = rest.slice(hashIndex + 1);
rest = rest.slice(0, hashIndex);
}
// extract query string
let query = {};
const queryIndex = rest.indexOf("?");
if (queryIndex !== -1) {
const queryString = rest.slice(queryIndex + 1);
query = Object.fromEntries(
queryString.split("&").map((pair) => pair.split("="))
);
rest = rest.slice(0, queryIndex);
}
// extract path
let path = "";
const pathIndex = rest.indexOf("/");
if (pathIndex !== -1) {
path = rest.slice(pathIndex);
rest = rest.slice(0, pathIndex);
}
// extract host and port
let host = rest;
let port = "";
const portIndex = rest.indexOf(":");
if (portIndex !== -1) {
host = rest.slice(0, portIndex);
port = rest.slice(portIndex + 1);
}
return { protocol, host, port, path, query, hash };
}
console.log(parseURL("https://www.example.com:8080/path/to/page?name=alice&age=25#section1"));
// {
// protocol: "https",
// host: "www.example.com",
// port: "8080",
// path: "/path/to/page",
// query: { name: "alice", age: "25" },
// hash: "section1"
// }
// 2. buildURL
function buildURL(base, params) {
const queryString = Object.entries(params)
.map(([key, value]) => `${key}=${value}`)
.join("&");
return `${base}?${queryString}`;
}
console.log(buildURL("https://api.example.com/search", {
q: "javascript",
page: 1,
limit: 10
}));
// "https://api.example.com/search?q=javascript&page=1&limit=10"