approaches = {
const makeLink = (item) => `[${item.title}](${item.url})`;
function mostFrequentTags(data, numTags = 5) {
console.log("mostFrequentTags", data);
const tagCounts = {};
data.forEach((item) => {
item.tags.forEach((tag) => {
tagCounts[tag] = (tagCounts[tag] || 0) + 1;
});
});
const topTags = Object.entries(tagCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, numTags)
.map(([tag]) => tag);
const result = {};
topTags.forEach((tag) => {
result[tag] = data
.filter((item) => item.tags.includes(tag))
.map(makeLink);
});
return result;
}
function uniqueTagAssignment(data) {
const result = {};
const usedItems = new Set();
data.forEach((item) => {
if (!usedItems.has(item.url)) {
const chosenTag = item.tags.reduce((a, b) =>
(result[a] || []).length <= (result[b] || []).length ? a : b
);
result[chosenTag] = (result[chosenTag] || []).concat(makeLink(item));
usedItems.add(item.url);
}
});
return result;
}
// Approach 3: Tag co-occurrence
function tagCoOccurrence(data, numPairs = 5) {
const coOccurrence = {};
data.forEach((item) => {
for (let i = 0; i < item.tags.length; i++) {
for (let j = i + 1; j < item.tags.length; j++) {
const pair = [item.tags[i], item.tags[j]].sort().join("-");
coOccurrence[pair] = (coOccurrence[pair] || 0) + 1;
}
}
});
const topPairs = Object.entries(coOccurrence)
.sort((a, b) => b[1] - a[1])
.slice(0, numPairs)
.map(([pair]) => pair.split("-"));
const result = {};
topPairs.forEach(([tag1, tag2]) => {
const combinedTag = `${tag1}-${tag2}`;
result[combinedTag] = data
.filter((item) => item.tags.includes(tag1) && item.tags.includes(tag2))
.map(makeLink);
});
return result;
}
// Approach 4: Chronological tag emergence
function chronologicalTagEmergence(data, numTags = 5) {
const tagFirstAppearance = {};
const result = {};
data.sort((a, b) => new Date(a.created) - new Date(b.created));
for (const item of data) {
for (const tag of item.tags) {
if (!(tag in tagFirstAppearance)) {
tagFirstAppearance[tag] = item.created;
if (Object.keys(result).length < numTags) {
result[tag] = [makeLink(item)];
} else {
return result;
}
}
}
}
return result;
}
// Approach 5: Tag diversity score
function tagDiversityScore(data, numTags = 5) {
const tagItems = {};
data.forEach((item) => {
item.tags.forEach((tag) => {
tagItems[tag] = (tagItems[tag] || []).concat(item);
});
});
const tagScores = Object.entries(tagItems).map(([tag, items]) => {
const uniqueUrls = new Set(items.map((item) => item.url));
return [tag, uniqueUrls.size / items.length];
});
const topDiverseTags = tagScores
.sort((a, b) => b[1] - a[1])
.slice(0, numTags)
.map(([tag]) => tag);
const result = {};
topDiverseTags.forEach((tag) => {
result[tag] = tagItems[tag].map(makeLink);
});
return result;
}
function tagDiversityScoreNoDuplicates(data, numTags = 10) {
// Helper function to calculate diversity score
const calculateDiversityScore = (items) => {
const uniqueUrls = new Set(items.map((item) => item.url));
return uniqueUrls.size / items.length;
};
// Group items by tag
const tagItems = {};
data.forEach((item) => {
item.tags.forEach((tag) => {
tagItems[tag] = (tagItems[tag] || []).concat(item);
});
});
// Calculate initial diversity scores
let tagScores = Object.entries(tagItems).map(([tag, items]) => ({
tag,
score: calculateDiversityScore(items),
items
}));
// Sort tags by diversity score
tagScores.sort((a, b) => b.score - a.score);
const result = {};
const usedItems = new Set();
// Iterate through sorted tags
for (const { tag, items } of tagScores) {
if (Object.keys(result).length >= numTags) break;
// Filter out already used items
const unusedItems = items.filter((item) => !usedItems.has(item.url));
if (unusedItems.length > 0) {
result[tag] = unusedItems.map(makeLink);
unusedItems.forEach((item) => usedItems.add(item.url));
// Recalculate score for remaining tags
tagScores = tagScores.map((ts) => ({
...ts,
items: ts.items.filter((item) => !usedItems.has(item.url)),
score: calculateDiversityScore(
ts.items.filter((item) => !usedItems.has(item.url))
)
}));
// Resort tags
tagScores.sort((a, b) => b.score - a.score);
}
}
return result;
}
// Function to generate markdown output
function generateMarkdown(approach, result) {
let markdown = `## ${approach}\n\n`;
for (const [tag, links] of Object.entries(result)) {
markdown += `**${tag}**: ${links.slice(0, 3).join(", ")}\n\n`;
}
return markdown;
}
// Usage example (assuming 'data' is your JSON data)
const approaches = [
{ name: "Most Frequent Tags", func: mostFrequentTags },
{ name: "Unique Tag Assignment", func: uniqueTagAssignment },
{ name: "Tag Co-occurrence", func: tagCoOccurrence },
{ name: "Chronological Tag Emergence", func: chronologicalTagEmergence },
{ name: "Tag Diversity Score", func: tagDiversityScore },
{
name: "Tag Diversity Score no dupes",
func: tagDiversityScoreNoDuplicates
},
{
name: "tagsWithThreePlusItems",
func: tagsWithThreePlusItems
}
];
// Generate and log results
return approaches;
}