简体   繁体   中英

How can I add elements from an array to an empty object in JavaScript?

I have a text file with two sentences, one on line 1 and the other sentence on line 2
Example:
line 1: The foo is black
line 2: The bar barks

The contents of line 1 and line 2 would be put inside of an array example: ['The foo is black', 'The bar barks']

Now that I have these two inside an array I want to loop through the array and put each word in the sentence inside of an object along with the line number it is on. Example:

{
    barks : 2 //line 2
    black : 1 //line 1
    foo: 1
    bar: 2
    is : 1
    the : 1, 2
}

how can I approach this? I thought that I could loop through the array and then add each word to an object but the output does not necessarily have to be in an object, that was just my thinking. It's important to note that the output must be sorted in alphabetical order as well.

I think the best approach is to stick with an array, which you can actually sort ( Map will prove difficult if and when you have the same word on multiple lines).

See this process:

 const data = ['The foo is black', 'The bar barks']; let output = new Array(); data.forEach((i, line) => { line++; // because line numbers start from 1 // split into words lowercase and include line number const words = i.split(' ').map(j => j.toLowerCase()).map(text => ({ text, line })); output.push(...words); }); // sort alphabetically output = output.sort((a, b) => (+(a.text > b.text) || -1)); console.log('Data sorted alphabetically with line numbers:', output);

As the order is important, the final result should better be an array of pairs. And since a word might occur multiple times in the same string, it might be interesting to not only mention the line number, but also the number of the word in that line:

 function wordOccurrences(lines) { const obj = {}; lines.forEach((lineStr, line) => lineStr.toLowerCase().match(/\S+/g).forEach((wordStr, word) => (obj[wordStr]??= []).push({line, word}) ) ); const result = Object.entries(obj).sort(([a], [b]) => a.localeCompare(b)); return result; } const result = wordOccurrences(['The foo is black', 'The bar barks']); console.log(result);

Using a Map , you can do this:

const lines = ['The foo is black', 'The bar barks'];

let wordCount = new Map();
for (let i = 0; i < lines.length; i++) {
    const words = lines[i].split(' ');
    for (const word of words) {
        let count = wordCount.get(word.toLowerCase()) || [];
        count.push(i + 1);
        wordCount.set(word.toLowerCase(), count);
    }
}

wordCount = new Map([...wordCount.entries()].sort());
console.log(wordCount);

I believe that this is the most understandable and idiomatic way to do this.

I know, there is already an accepted answer. However, this is my take on it. It will work on "modern" browsers on which the insertion order of keys in objects is respected. The snippet produces an object obj in which the individual words are the keys. They appear in an alphabetically sorted order. The associated values are arrays containing the line numbers in which the key (word) appears:

 const str=`The foo is black The bar barks And the last 1 is stupid and has 12 words in it`; obj=Object.fromEntries( Object.entries( str.toLowerCase().split("\n").reduce((a,line,i)=>{ line.split(/\s+/).forEach(w=>(a[w]??={})[i+1]=1); return a; },{}) ).sort(([a],[b])=>a.localeCompare(b)).map(([k,v])=>[k,Object.keys(v).map(k=>+k)]) ); console.log(obj);

The expression .sort(([a],[b])=>a.localeCompare(b)).map(([k,v])=>[k,Object.keys(v).map(k=>+k)]) is at the heart of the operation. It sorts the keys of the overall object and converts their values (also originally objects with string typed keys) back into arrays of numbers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM