לדלג לתוכן

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"