プライベートな連絡先の最初の情報
送料メール:
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
この記事は、面接プロセス中に遭遇したコーディングに関する質問をまとめたものです。
返される真の値はフィルタリングではなく保持用であるため、忘れないでください。何でもない、半年も直接書かないと忘れてしまうだけだ。 。 。
arr.filter((項目, インデックス, 現在) => {return arr.indexOf(item) == インデックス});。重量を取り除くことができます
フィルターの本質は新しい配列を作成することであり、コールバック関数が true を返した場合、その配列は保持されます。上記のコード行は、最初の時間のみが内部に配置されることを意味します。
ダブルポインターの重複排除:
ダブルポインタを使用して配列を並べ替えます。それらが等しい場合、高速ポインタは 1 つ右に移動し、高速ポインタは 1 つ右に移動します。次回との比較のために右への高速ポインタ:
- function doublePointer(nums) {
- if(nums.length < 2) {
- return nums;
- }
- let slow = 0;
- let fast = 1;
- let result = [nums[0]];
- while(fast < nums.length) {
- if (result[slow] == nums[fast]) {
- fast++;
- } else {
- slow++;
- result[slow] = nums[fast];
- fast++;
- }
- }
- return result;
- }
- const arr = [1,1,2,2,4,4];
- console.log(doublePointer(arr));
[1,1,2,2,4,4]を入力し、[1,2,4]を出力します。
配列がオブジェクトの場合:
定数 arr2 = [{id:1,time: 2},{id:1,time: 4},{id:2,time: 2},{id:2,time: 4},{id:3,time: 5},
{id:3,時間: 2}];
ここで、ID に基づいて重複を削除する必要があります。ID が等しい場合、最大の時間を持つオブジェクトのみが保持されます。
[{"id":1,"時間":4},{"id":2,"時間":4},{"id":3,"時間":5}]
- function doublePointerByorder(nums) {
- if(nums.length < 2) {
- return nums;
- }
- let slow = 0;
- let fast = 1;
- let result = [nums[0]];
- while(fast < nums.length) {
- if (result[slow].id == nums[fast].id) {
- if(result[slow].time < nums[fast].time) {
- result[slow] = nums[fast];
- }
- fast++;
- } else {
- slow++;
- result[slow] = nums[fast];
- fast++;
- }
- }
- return result;
- }
console.log(doublePointerByorder(arr2)); 以上です。
もちろん、空のオブジェクトを使用して、その都度、オブジェクト内の ID に対応する時間を比較し、上書きするかどうかを選択することもできます。走査後、for in ループを使用してオブジェクトを配列に変換します。ただし、データ量が大きい場合は、ダブル ポインターを使用する方が効率的です。
参照型変数の等号の割り当ては相互に影響しません。
ただし、以下に示すように、浅いコピーとみなされる ab を使用すると影響を受けます。
- person1 = {name: 3};
- members = person1;
- members.name = 4; // person1.name=4
引用に関連する典型的なケースを見てみましょう。これは、私がインタビュー中に初めて遭遇したときにメモしなかった質問でもありました。配列をツリー構造に変換します。
- function arrayToTree(items) {
- const tree = {};
- const map = {};
- items.forEach((item, index) => {
- const { id, parentId } = item;
- if (!map[id]) map[id] = { children: [] };
- const node = { ...item, children: map[id].children};
- map[id] = node;
- if (parentId) {
- if (!map[parentId]) {
- map[parentId] = { children: [] };
- } map[parentId].children.push(node);
- } else {
- tree[id] = node;
- }
- });
- console.log(map);
- }
-
- // 示例数组
- const items = [
- { id: 1, parentId: null, value: "A" },
- { id: 2, parentId: 1, value: "B" },
- { id: 3, parentId: 1, value: "C" },
- { id: 4, parentId: 2, value: "D" },
- { id: 5, parentId: 3, value: "E" }
- ];
-
- // 转换为树
- const tree = arrayToTree(items);
ロシアのマトリョーシカ人形のように、直接コピーして効果を確認できます。最初のレイヤーに 2 番目のレイヤーを追加すると、わかりやすいです。難しいのは、2 番目のレイヤーに 3 番目のレイヤーを追加する場合です。実際、よく考えてみると、a["1"] の下に a["1"].children["2"] があることがわかります。とその値が a["2"] と等しいだけでなく、参照もすべて同じなので、 a["1"].children.push(a["2"]); を実行します。この利点は、a["3"]={...item,children:[]} が実行されたとき、a["2"].children.push(a["3"]) が実行されたときに得られます。操作データなので、同じ参照を持つ場所 (たとえば、a=b、b.push は a.push にも影響します) もプッシュされるため、a["1"].children["2"] が表示されます。 .children a["3"]。これは正しいツリー構造です。
それでも理解できない場合は、次のことを試してみてください。
上に示すように、b1 は a1 の第 1 レベルのノードとみなされ、b1 を変更すると a1 に影響します。上記はループですが、各スコープ内の参照は同じです。
2 4 5 同期コード、3 マイクロ タスク、1 マクロ タスク。唯一の落とし穴は、4 は出力されますが、return 3 は実行されないことです。
暗黙的な変換比較中に、配列は toString メソッドを呼び出します。
これまでに書いたことがない場合は、面接中に破る必要がありますが、破ることができない可能性が高くなります。以下は、アンチシェイクの即時実行と遅延実行、スロットリングの即時実行と遅延実行です。
- function debounce(fn, delay) {
- let timer = null;
- return function (...args) {
- timer && clearTimeout(timer);
- timer = setTimeout(() => {
- fn.apply(this, args);
- }, delay);
- }
- }
-
- function debounce_immediate(fn, delay, immediate = false) {
- let timer = null;
- let flag = true;
- return function (...args) {
- timer && clearTimeout(timer);
- if (immediate) {
- if (flag) {
- fn.apply(this, args);
- flag = false;
- }
- timer = setTimeout(() => {
- flag = true;
- }, delay);
-
- } else {
- timer = setTimeout(() => {
- fn.apply(this, args);
- }, delay);
- }
- }
- }
-
- function throttle(fn, delay) {
- let lastTime = 0;
- let timer = null;
- return function (...args) {
- const nowTime = Date.now();
- if (nowTime - lastTime > delay) {
- fn.apply(this, args);
- lastTime = nowTime;
- }
- }
- }
-
- function throttle_D(func, delayTime) {
- let delay = delayTime || 1000;
- let timer = null;
- return function (...args) {
- if (!timer) {
- timer = setTimeout(function () {
- func.apply(this, args);
- timer = null;
- }, delay);
- }
- }
- }
必ず引数を指定してください。アンチシェイクとスロットルの本質的な違いは、アンチシェイクは常にタイマーをリセットしますが、スロットルは常にトリガーされず、一定の時間間隔内で 1 回だけ実行されることです。手ぶれ補正が 1 分間トリガーされる場合、それは 1 回だけ実行されます (即時実行または最後のクリックによってトリガーされる遅延実行)。